【Flutter造輪子】Text元件顯示指定行文字,若有超出加...點選檢視更多
阿新 • • 發佈:2021-02-06
技術標籤:Flutter
效果如上圖,如果超出,顯示“…點選檢視更多”,正好湊夠4行,再新增一個字便超出4行。
原理: 使用TextPainter逐漸新增字嘗試,該元件超出的話,其屬性didExceedMaxLines為true
程式碼如下:
///文字超出一定行,自動隱藏,並新增入"...檢視更多詳情"為它設定點選事件
class HideText extends StatefulWidget {
HideText({
@required this.text, //正常字
this.style, //正常字樣式
@required this.additionText, //附加字,如點選檢視更多
this.additionStyle, //附加字的樣式
this.maxLines = 3, //行數,不傳 預設為3
this.additionUrl, //點選附加字跳轉URL
this.additionParams, //點選附加字跳轉時攜帶的引數
}) : assert(text != null),
assert(additionText != null);
final String text;
final TextStyle style;
final String additionText;
final TextStyle additionStyle;
final int maxLines;
final String additionUrl;
final Map<String, dynamic> additionParams;
@override
_HideTextState createState() => _HideTextState();
}
class _HideTextState extends State<HideText> {
@override
Widget build (BuildContext context) {
return Container(
padding: EdgeInsets.only(top: 10),
child: _textPaint([TextSpan(text: widget.text, style : widget.style)]).didExceedMaxLines ? RichText(
text: TextSpan(
children: [
TextSpan(
text: "${widget.text.substring(0, _fontNum())}",
style: widget.style,
),
TextSpan(
children: [
TextSpan(text: "...", style: widget.style),
TextSpan(text: "${widget.additionText}", style: widget.additionStyle)
],
recognizer: TapGestureRecognizer()
..onTap = (){
if(isNotBlank(widget.additionUrl)) {
FlutterBoost.singleton.open(widget.additionUrl);
}
}
)
]
),
) : Container( //未超出指定行數的話全部顯示
child: Text(
widget.text,
style: widget.style,
),
),
);
}
TextPainter _textPaint(List<InlineSpan> children){
return TextPainter(
maxLines: widget.maxLines,
text: TextSpan(
children: children
),
textDirection: TextDirection.ltr)
..layout(maxWidth: UIUtils.screenWidth(context) - 40); //若新功能寬度不一致,可嘗試修改,
//UIUtils.screenWidth(context)是自定義的獲取螢幕寬度的方法
}
int _fontNum(){ //計算最多可容納正常字的數目,可優化
int num = 0;
int skip = 1;
while(true){
bool isExceed = widget.text.length < num + skip || _textPaint([TextSpan(text: widget.text.substring(0, num + skip) + "...", style: widget.style),
TextSpan(text: widget.additionText, style: widget.additionStyle)]).didExceedMaxLines;
if(!isExceed) {
num = num + skip;
skip *= 2;
continue;
}
if(isExceed && skip == 1){
return num;
}
skip = skip ~/ 2;
}
}
}
在此基礎上可以根據需求改造,如點選檢視更多顯示所有內容等功能,不做贅述。