Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >【Flutter 专题】137 图解自定义 ACEFoldTextView 折叠文本

【Flutter 专题】137 图解自定义 ACEFoldTextView 折叠文本

作者头像
阿策小和尚
发布于 2021-10-12 08:02:14
发布于 2021-10-12 08:02:14
1.3K00
代码可运行
举报
文章被收录于专栏:阿策小和尚阿策小和尚
运行总次数:0
代码可运行

和尚在学习 Flutter 过程中,有特别需求是对于文本过长的内容需要展示固定行数,而在文本右下角有提示用户点击展开和收起;和尚尝试自定义一个可折叠收缩的 ACEFoldTextView

ACEFoldTextView

和尚首先简单梳理了一下设计流程,如下图所示;

  • 当文本内容所占据行数小于等于限制的最大行数时,默认展示整个文本内容,不会有【展开/收起】;
  • 当文本内容所占据行数大于限制的最大行数时,默认展示最大行数内容,并在右下角显示【展开】提示;
  • 点击【展开】区域时,当文本内容最后一行内容与【展开】区域占据内容宽度之和小于最大宽度时,默认展示【收起】;
  • 点击【展开】区域时,当文本内容最后一行内容与【展开】区域占据内容宽度之和大于等于最大宽度时,【收起】区域换行展示;

1. 透明渐变【展开/收起】

和尚整体通过 Stack 层级嵌套方式在右下角显示可点击的【展开/收起】文本区,为了提高显示效果,并防止完全遮挡内容文本,和尚尝试了两种方式来实现颜色透明度渐变;

1.1 ShaderMask 着色器

和尚之前有重点介绍过 ShaderMask 着色器,可以对子 Widget 进行颜色处理,包括遮罩层特效展示;和尚设置了一个 LinearGradient 线性渐变,但 ShaderMask 是对整个子 Widget 遮罩层生效,可能会影响 Text 文本显示效果,需要 Stack 层级使用;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
_transparentWid02() => ShaderMask(
    shaderCallback: (bounds) => LinearGradient(
          colors: [_bgColor.withOpacity(0.0), _bgColor],
        ).createShader(bounds),
    child: Container(
        alignment: Alignment.centerRight,
        color: Colors.white,
        width: _kMoreWidth,
        child: Text((_temLines > _maxLines) ? '展开' : '收起',
            style: TextStyle(color: Theme.of(context).accentColor, fontSize: widget.textStyle?.fontSize ?? 14.0))));
1.2 Container BoxDecoration

第二种就是常用的 Container 配合设置 BoxDecoration 设置线性渐变色;该方式使用更为便捷;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
_transparentWid01() => Container(
    alignment: Alignment.centerRight,
    decoration: BoxDecoration(
        gradient: LinearGradient(
            colors: [_bgColor.withOpacity(0.0), _bgColor],
            end: FractionalOffset(0.5, 0.5))),
    width: _kMoreWidth,
    child: Text((_temLines > _maxLines) ? '展开' : '收起',
        style: TextStyle(color: Theme.of(context).accentColor, fontSize: widget.textStyle?.fontSize ?? 14.0)));

2. Text 文本内容折叠

和尚想实现文本折叠,首先需要预先得知 Text 文本在范围内占据的行数,一般都需要通过 TextPainter 等方式获取;和尚尝试了两种方式进行判断;

2.1 TextPainter.didExceedMaxLines

和尚之前也有简单了解过 TextPainterTextSpan 的应用,主要用于文本的绘制,当设置 maxLines 之后,可以通过 didExceedMaxLines 判断文本内容是否已经超行;和尚之后会对 TextPainter 再深入研究一下;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
_checkOverMaxLines01(maxLines, maxWidth) {
  final textSpan = TextSpan(text: _textStr, style: widget.textStyle);
  final textPainter = TextPainter(text: textSpan, textDirection: TextDirection.ltr, maxLines: maxLines);
  textPainter.layout(maxWidth: widget.maxWidth ?? MediaQuery.of(context).size.width);
  return textPainter.didExceedMaxLines;
}
2.2 LineMetrics

didExceedMaxLines 可以直接获取文本内容是否超行,但无法获取每行文本信息等;于是和尚尝试了 computeLineMetrics() 方式获取 LineMetrics 基线度量;可以获取每行内容所占据的宽高等;

当然 LineMetrics 也无法获取每行文本内容,以及在两种文本对齐方式共用时有注意事项,和尚之后会进一步研究;

Tips: 在使用 computeLineMetrics() 获取 LineMetrics 信息时,需要注意 TextPainter 必须设置好 textDirection 文本对齐方式,以及在 layout 布局之后才可以获取;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
_checkOverMaxLines02(maxWidth) {
  final textSpan = TextSpan(text: _textStr, style: widget.textStyle);
  final textPainter = TextPainter(text: textSpan, textDirection: TextDirection.ltr);
  textPainter.layout(maxWidth: widget.maxWidth ?? MediaQuery.of(context).size.width);
  _lines = textPainter.computeLineMetrics();
  return _lines;
}

3. ACEFoldTextView

有了前面两步的基础,和尚将其结合起来,生成自定义 ACEFoldTextView;通过 LinearBuilder 约束子 Text 延迟加载;通过 LineMetrics 获取最后一行文本长度,与默认【展开】所在 Widget 计算总和,之后判断是否占据超过限制最大宽度;当超过最大宽度时,和尚将文本添加一个 \n 强制换行;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
return LayoutBuilder(builder: (context, size) {
  _isOverFlow = _checkOverMaxLines01(_maxLines, widget.maxWidth);
  _temLines = _checkOverMaxLines02(widget.maxWidth)?.length;
  return (_temLines <= _maxLines)
      ? _itemText() : Stack(children: <Widget>[_itemText(), _moreText()]);
});

_moreText() => Positioned(
      bottom: 0, right: 0,
      child: GestureDetector(
          child: _transparentWid02(),
          onTap: () => setState(() {
                if (_temLines > _maxLines) {
                  if (_lines.last.width + _kMoreWidth >= widget.maxWidth) {
                    _maxLines = _temLines + 1;
                    _textStr = '${widget.text}\n';
                  } else {
                    _maxLines = _temLines;
                  }
                } else if (_temLines == _maxLines) {
                  _maxLines = widget.maxLines;
                }
              })));

ACEFoldTextView 案例源码


和尚对 ACEFoldTextView 的绘制到此为止,其中涉及到 TextPainter 内容较浅显,和尚之后会进一步学习研究;如有错误,请多多指导!

来源:阿策小和尚

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-09-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 阿策小和尚 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Flutter的Container组件与Text组件详解
首先复习一下Flutter项目的基本结构: import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget{ @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(
拉维
2019/08/12
6270
带你深入理解 Flutter 中的字体“冷”知识
本篇将带你深入理解 Flutter 开发过程中关于字体和文本渲染的“冷”知识,帮助你理解和增加关于 Flutter 中字体绘制的“无用”知识点。
GSYTech
2020/06/02
1.4K0
带你深入理解 Flutter 中的字体“冷”知识
Flutter 中 TextField 组件必然会遇到的问题
TextField 组件几乎是开发中必然会用到的一个组件,在使用的过程中会遇到两个非常棘手的问题:
老孟Flutter
2021/11/25
3.2K0
Flutter 中 TextField 组件必然会遇到的问题
【Flutter 专题】32 Flutter 32: 图解 TextPainter 与 TextSpan 小尝试
大家在学习 Flutter 时一定会用过 Text,而对于一些复杂文本的处理可能会选择 RichText,再进一步,使用 RichText 就一定要用 TextSpan ,和尚本以为可以做为一个小知识点进行简单学习,但是随着深入尝试发现 TextSpan 涉及东西很多,很值得研究,因此单独整理一篇小博文。
阿策小和尚
2019/08/12
2K0
【Flutter 专题】32 Flutter 32: 图解 TextPainter 与 TextSpan 小尝试
【Flutter 专题】118 图解特殊利器 ShaderMask 着色器
和尚在尝试把图片做成黑白色时,了解到 ShaderMask 这个利器,今天和尚简单学习和尝试一下;
阿策小和尚
2021/04/02
9140
【Flutter 专题】52 图解可折叠状态栏
和尚以前在学习滑动冲突时曾用过 Sliver 系列的 Widget,和尚这次尝试用 SliverAppBar 来处理;
阿策小和尚
2019/08/12
1.4K0
【Flutter 专题】52 图解可折叠状态栏
【Flutter 专题】30 图解自定义底部状态栏 ACEBottomNavigationBar (一)
和尚刚接触 Flutter 时接触到底部状态栏 BottomNavigationBar 方便快捷,但随着使用过程发现依然有一些限制,包括图片选择/样式凸出/固定 NavigationItem 位等。和尚不才,准备照葫芦画瓢,自定义一个底部状态栏,并尝试封装成一个 pub 插件。
阿策小和尚
2019/08/12
1.3K0
【Flutter 专题】30 图解自定义底部状态栏 ACEBottomNavigationBar (一)
【Flutter 组件】002-基础组件:文本与样式
继承关系: Text -> StatelessWidget -> Widget -> DiagnosticableTree -> Diagnosticable -> Object
訾博ZiBo
2025/01/06
1100
【Flutter 组件】002-基础组件:文本与样式
【Flutter 专题】117 图解 Dismissible 滑动清除 Widget
和尚在尝试在项目中实现类似于 iOS 邮箱邮件左右滑动删除对应邮件时,参考到 Flutter 提供的 Dismissible,虽与理想的有差别,但还是值得研究一下。
阿策小和尚
2021/03/16
1.3K0
【Flutter 专题】25 易忽略的【小而巧】的技术点汇总(三)
和尚为了给添加渐变色背景,需要用到 LinearGradient,和尚尝试时发现如下注意。
阿策小和尚
2019/08/12
1.2K0
【Flutter 专题】25 易忽略的【小而巧】的技术点汇总(三)
【Flutter 专题】56 自定义 BubbleWidget 气泡插件
和尚在学习时想要用到气泡效果,为了更加灵活,和尚封装了一个简单的气泡插件,方便日常的使用;
阿策小和尚
2019/08/12
1.6K0
【Flutter 专题】56 自定义 BubbleWidget 气泡插件
Flutter基础widgets教程-OverflowBox篇
1 OverflowBox 对其子项施加不同约束的widget,它可能允许子项溢出父级 2 构造函数 OverflowBox({ Key key, this.alignment = Alignment.center, this.minWidth, this.maxWidth, this.minHeight, this.maxHeight, Widget child, }) 3 常用属性 3.1 alignment:对齐方式 alignment:Alig
青年码农
2020/10/16
3.2K0
Flutter基础widgets教程-OverflowBox篇
Flutter布局基础——Stack层叠布局
Stack Widget的子视图要么是positioned,要么是non-positioned。Positioned子视图是指使用Positioned的widget包括起来的子视图,通过设置相对于Stack的top、bottom、left、right属性来确认自身位置,其中至少要有一个不为空。
莫空9081
2021/07/27
3.2K0
Flutter自定义view —— 闯关进度条
但我觉得还是用自定义 view 实现效果比较好,想要什么效果都可以去实现,所以我按照
CatEatFish
2020/07/09
1K0
Flutter自定义view —— 闯关进度条
『Flutter』项目实战(苹果计算器)搭建页面布局
经过上一篇文章的介绍,已经完成了项目的初始化,以及项目与容器的搭建,接下来就是搭建页面布局了。
杨不易呀
2024/01/29
3350
『Flutter』项目实战(苹果计算器)搭建页面布局
用Flutter构建漂亮的UI界面 – 基础组件篇
Flutter作为时下最流行的技术之一,凭借其出色的性能以及抹平多端的差异优势,早已引起大批技术爱好者的关注,甚至一些闲鱼,美团,腾讯等大公司均已开始使用。虽然目前其生态还没有完全成熟,但身靠背后的Google加持,其发展速度已经足够惊人,可以预见将来对Flutter开发人员的需求也会随之增长。
Javanx
2019/09/04
2.8K0
用Flutter构建漂亮的UI界面 – 基础组件篇
【Flutter 专题】67 图解基本约束 Box (二)
分析源码可得,UnconstrainedBox 继承自 SingleChildRenderObjectWidget,与 ConstrainedBox 效果相反,给子 Widget 提供不加限制的空间;
阿策小和尚
2019/11/12
5620
【Flutter 专题】67 图解基本约束 Box (二)
flutter系列之:flutter中常用的Stack layout详解
对于现代APP的应用来说,为了更加美观,通常会需要用到不同图像的堆叠效果,比如在一个APP用户背景头像上面添加一个按钮,表示可以修改用户信息等。
程序那些事
2022/09/20
7010
【Flutter 专题】64 图解基本 TextField 文本输入框 (一)
和尚最近在学习基础的 Flutter Widget,原因在于很多基础的组件有很多容易忽视的注意事项,了解并熟悉后对整体的开发认知会有所提升;今天和尚学习一下 TextField 文本输入框;
阿策小和尚
2019/10/22
4.8K0
Flutter | 常用组件分类、概述、实战
AppBar(title属性,Text组件; action:动作响应;!!!! titleSpacing:标题文字间距; toolbarOpacity:标题透明度;)
凌川江雪
2020/06/16
4.3K0
推荐阅读
相关推荐
Flutter的Container组件与Text组件详解
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验