Flutter如何在长文本末尾添加展开收起图标实现折叠效果
Flutter 长文本末尾带展开/收起图标实现方案
核心调整点
- 替换原有固定字符长度截断逻辑,改为按最大行数判断是否需要折叠,适配不同屏幕、字体大小的显示场景
- 使用
RichText结合WidgetSpan将图标嵌入文本末尾,实现图标与文本对齐的效果 - 优化交互逻辑,折叠/展开状态切换流畅
完整可运行代码
import 'package:flutter/material.dart'; class HomeScreen extends StatelessWidget { final String description = "Flutter is Google’s mobile UI framework for crafting high-quality native interfaces on iOS and Android in record time. Flutter works with existing code, is used by developers and organizations around the world, and is free and open source."; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("Demo App"), ), body: Container( padding: const EdgeInsets.all(16), child: DescriptionTextWidget(text: description, maxLines: 2), ), ); } } class DescriptionTextWidget extends StatefulWidget { final String? text; final int maxLines; // 自定义折叠状态下最大显示行数 const DescriptionTextWidget({ super.key, required this.text, this.maxLines = 2, }); @override _DescriptionTextWidgetState createState() => _DescriptionTextWidgetState(); } class _DescriptionTextWidgetState extends State<DescriptionTextWidget> { bool _isExpanded = false; @override Widget build(BuildContext context) { if (widget.text == null || widget.text!.isEmpty) { return const SizedBox.shrink(); } return LayoutBuilder( builder: (context, constraints) { // 用TextPainter判断文本是否超过最大行数 final textSpan = TextSpan( text: widget.text!, style: DefaultTextStyle.of(context).style, ); final textPainter = TextPainter( text: textSpan, maxLines: widget.maxLines, textDirection: TextDirection.ltr, )..layout(maxWidth: constraints.maxWidth); final isOverflow = textPainter.didExceedMaxLines; if (!isOverflow) { // 文本未溢出,直接显示 return Text(widget.text!); } // 文本溢出,处理折叠/展开逻辑 return InkWell( onTap: () { setState(() { _isExpanded = !_isExpanded; }); }, child: RichText( text: TextSpan( style: DefaultTextStyle.of(context).style, children: [ TextSpan( text: _isExpanded ? widget.text! : widget.text!.substring(0, textPainter.getPositionForOffset(Offset(constraints.maxWidth, textPainter.size.height)).offset - 3) + '... ', ), WidgetSpan( alignment: PlaceholderAlignment.middle, child: Icon( _isExpanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down, size: 18, color: Colors.grey, ), ), ], ), maxLines: _isExpanded ? null : widget.maxLines, ), ); }, ); } }
功能说明
- 可通过
maxLines参数自定义折叠状态下的最大显示行数,默认2行 - 文本未超出最大行数时不会显示折叠/展开图标
- 点击文本或图标都可以触发折叠/展开切换,交互范围更大
- 图标与文本底部对齐,符合设计效果要求
内容的提问来源于stack exchange,提问作者Deepak
相关产品推荐
相关产品推荐

