一、需求来源
开发时遇到一个需求需要在文字超过一行时有展开和收起菜单,效果如下:
二、使用示例
Header.h4(title: "字符串不够一行时"),
Container(
color: Colors.yellowAccent,
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
child: NExpandText(
text: text.substring(0, 20),
textStyle: textStyle,
expandTitleStyle: TextStyle(color: Colors.green)
),
),
Header.h4(title: "字符串超过一行时(折叠)"),
Container(
color: Colors.yellow,
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
child: NExpandText(
text: text,
textStyle: textStyle,
expandTitleStyle: TextStyle(color: Colors.green)
),
),
Header.h4(title: "字符串超过一行时(展开)"),
Container(
color: Colors.yellow,
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
child: NExpandText(
text: text,
textStyle: textStyle,
expandTitleStyle: TextStyle(color: Colors.green)
),
),
三、组件源码
import 'package:flutter/material.dart';
import 'package:flutter_templet_project/extension/text_painter_ext.dart';
///如果文字超过一行,右边有展开收起按钮
class NExpandText extends StatefulWidget {
NExpandText({
Key? key,
required this.text,
required this.textStyle,
this.expandMaxLine = 10,
this.expandTitleStyle,
this.initiallyExpanded = false,
}) : super(key: key);
/// 字符串
String text;
/// 字符串样式
TextStyle textStyle;
/// 超过一行初始展开状态
bool initiallyExpanded;
/// 展开状态最大行
int expandMaxLine;
/// 展开按钮文字样式
TextStyle? expandTitleStyle;
@override
_NExpandTextState createState() => _NExpandTextState();
}
class _NExpandTextState extends State<NExpandText> {
@override
Widget build(BuildContext context) {
return buildText(
text: widget.text,
textStyle: widget.textStyle,
isExpand: widget.initiallyExpanded,
expandMaxLine: widget.expandMaxLine,
expandTitleStyle: widget.expandTitleStyle,
);
}
buildText({
required String text,
required TextStyle textStyle,
bool isExpand = false,
int expandMaxLine = 10,
TextStyle? expandTitleStyle,
}) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints){
final textPainter = TextPainterExt.getTextPainter(
text: text,
textStyle: textStyle,
maxLine: 100,
maxWidth: constraints.maxWidth,
);
final numberOfLines = textPainter.computeLineMetrics().length;
// debugPrint("numberOfLines:${numberOfLines}");
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
final btnTitle = isExpand ? "收起" : "展开";
return Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(19))
),
child: Container(
// color: Colors.green,
padding: EdgeInsets.symmetric(vertical: 8),
child: Text(text,
style: textStyle,
maxLines: isExpand ? expandMaxLine : 1,
),
),
),
),
if(numberOfLines > 1) TextButton(
style: TextButton.styleFrom(
padding: EdgeInsets.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
minimumSize: Size(50, 18),
),
onPressed: (){
isExpand = !isExpand;
setState((){});
},
child: Text(btnTitle, style: expandTitleStyle,),
),
],
);
}
);
}
);
}
}
总结
核心是通过 TextPainter 布局后获取行数代码:
final numberOfLines = textPainter.computeLineMetrics().length;
然后做尺寸判断进行处理,目前最优的方法。
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓(文末还有ChatGPT机器人小福利哦,大家千万不要错过)
PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题