Flutter如何实现Rich Text自定义截断

在Flutter中如何实现Rich Text的自定义截断功能?目前系统提供的TextOverflow.ellipsis只能显示简单省略号,但需求是要在富文本中根据特定条件截断(比如保留前两行,末尾添加自定义的"展开"按钮)。尝试过使用TextPainter计算字符位置,但处理不同样式的文本时效果不理想。请问有没有成熟的方案或插件可以实现这种富文本的智能截断?

2 回复

Flutter中可通过Text.rich结合TextSpan自定义富文本,截断可借助TextOverflow属性,或使用TextPainter计算文本布局,手动截断并添加自定义省略号。

更多关于Flutter如何实现Rich Text自定义截断的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中实现Rich Text自定义截断,可以通过以下方法:

1. 使用Text.rich + maxLines + overflow

Text.rich(
  TextSpan(
    children: [
      TextSpan(text: '这是一段需要截断的文本,'),
      TextSpan(
        text: '这部分是特殊样式',
        style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold),
      ),
      TextSpan(text: ',继续其他内容。'),
    ],
  ),
  maxLines: 2,
  overflow: TextOverflow.ellipsis,
)

2. 自定义截断组件(推荐)

class CustomTruncatedText extends StatelessWidget {
  final String text;
  final int maxLines;
  final TextStyle? style;
  
  const CustomTruncatedText({
    super.key,
    required this.text,
    this.maxLines = 2,
    this.style,
  });

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        final textSpan = TextSpan(text: text, style: style);
        final textPainter = TextPainter(
          text: textSpan,
          maxLines: maxLines,
          textDirection: TextDirection.ltr,
        );
        
        textPainter.layout(maxWidth: constraints.maxWidth);
        
        if (textPainter.didExceedMaxLines) {
          // 找到截断位置并添加自定义标记
          final position = textPainter.getPositionForOffset(
            Offset(constraints.maxWidth, textPainter.height),
          );
          
          final truncatedText = text.substring(0, position.offset) + '...';
          
          return Text(
            truncatedText,
            style: style,
            maxLines: maxLines,
            overflow: TextOverflow.clip,
          );
        }
        
        return Text(text, style: style);
      },
    );
  }
}

3. 使用auto_size_text包

在pubspec.yaml中添加:

dependencies:
  auto_size_text: ^3.0.0

使用:

AutoSizeText.rich(
  TextSpan(
    children: [
      TextSpan(text: '自定义截断文本'),
      TextSpan(
        text: '特殊部分',
        style: TextStyle(color: Colors.blue),
      ),
    ],
  ),
  maxLines: 2,
  overflow: TextOverflow.ellipsis,
)

主要方案对比

  • Text.rich:简单场景使用
  • 自定义组件:完全控制截断逻辑
  • auto_size_text:自动调整字体大小

根据需求复杂度选择合适的方案即可。

回到顶部