Flutter实现内容溢出时显示剩余项数量的Row组件
Flutter 实现溢出隐藏并显示剩余项数量的 Row 组件
要实现这种"内容溢出时隐藏多余项并显示剩余数量"的Row组件,核心是先测量每个子项的宽度,结合可用空间计算能容纳的项数,再选择性渲染。以下是完整的可复用组件实现:
完整代码
import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; class OverflowRow extends StatefulWidget { final List<String> texts; final TextStyle? textStyle; final TextStyle? remainingStyle; const OverflowRow({ super.key, required this.texts, this.textStyle, this.remainingStyle, }); @override State<OverflowRow> createState() => _OverflowRowState(); } class _OverflowRowState extends State<OverflowRow> { int _visibleCount = 0; int get _remainingCount => widget.texts.length - _visibleCount; @override void didUpdateWidget(covariant OverflowRow oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.texts != widget.texts) _calculateVisibleItems(); } @override void didChangeDependencies() { super.didChangeDependencies(); _calculateVisibleItems(); } void _calculateVisibleItems() { if (widget.texts.isEmpty) { setState(() => _visibleCount = 0); return; } final renderBox = context.findRenderObject() as RenderBox?; if (renderBox == null) return; final availableWidth = renderBox.size.width; final textPainter = TextPainter(textDirection: TextDirection.ltr); // 先计算剩余数量组件的宽度(含额外间距) textPainter.text = TextSpan( text: "+$_remainingCount", style: widget.remainingStyle ?? widget.textStyle, ); textPainter.layout(); final remainingWidth = textPainter.width + 8; double totalWidth = 0; int count = 0; // 逐个累加文本宽度,直到空间不足 for (final text in widget.texts) { textPainter.text = TextSpan(text: text, style: widget.textStyle); textPainter.layout(); final textWidth = textPainter.width + 8; if (totalWidth + textWidth + remainingWidth <= availableWidth) { totalWidth += textWidth; count++; } else { break; } } // 所有项都能放下时,不显示剩余计数 setState(() => _visibleCount = count == widget.texts.length ? widget.texts.length : count); } @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { // 布局完成后重新计算,确保尺寸准确 WidgetsBinding.instance.addPostFrameCallback((_) => _calculateVisibleItems()); final children = <Widget>[]; // 添加可见的文本项 for (int i = 0; i < _visibleCount; i++) { children.add( Padding( padding: const EdgeInsets.only(right: 8), child: Text(widget.texts[i], style: widget.textStyle), ), ); } // 添加剩余数量标识(如果有剩余) if (_remainingCount > 0) { children.add( Text( "+$_remainingCount", style: widget.remainingStyle ?? widget.textStyle, ), ); } return Row(children: children); }, ); } } // 使用示例 class DemoPage extends StatelessWidget { const DemoPage({super.key}); @override Widget build(BuildContext context) { final texts = ["Apple", "Banana", "Cherry", "Date", "Elderberry", "Fig", "Grape"]; return Scaffold( appBar: AppBar(title: const Text("溢出Row示例")), body: Padding( padding: const EdgeInsets.all(16), child: OverflowRow( texts: texts, textStyle: const TextStyle(fontSize: 16), remainingStyle: const TextStyle(fontSize: 16, color: Colors.grey), ), ), ); } }
关键说明
- 尺寸测量:用
TextPainter预计算文本和剩余计数组件的宽度,避免实际渲染后才发现空间不足 - 动态适配:通过
didChangeDependencies、didUpdateWidget和LayoutBuilder确保布局或数据变化时重新计算可见项数 - 间距处理:给文本和剩余计数添加额外间距,提升视觉体验
- 边界情况:当所有文本都能容纳时,自动隐藏剩余计数组件
内容的提问来源于stack exchange,提问作者Łukasz Mysłajek
相关产品推荐
相关产品推荐

