【Flutter造轮子】Text组件显示指定行文字,若有超出加...点击查看更多

本文介绍了一种实现文本超出指定行数自动隐藏并添加‘...点击查看更多’的方法,利用TextPainter逐步添加字符判断是否超出限制。当文本超出最大行数时,显示省略号及附加文字,附加文字具有点击事件,可用于打开链接或展示完整内容。
摘要由CSDN通过智能技术生成

样例
效果如上图,如果超出,显示“…点击查看更多”,正好凑够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;
    }
  }
}

在此基础上可以根据需求改造,如点击查看更多显示所有内容等功能,不做赘述。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值