You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何避免Row水平溢出并显示省略号

Flutter Row溢出时用省略号替代溢出内容

问题描述

我有一个包含多个子组件的Row,当屏幕宽度较小时会出现水平溢出报错。我不想使用Wrap组件让溢出的子项换行显示,而是希望溢出部分直接替换成省略号(...)或者自定义组件,比如当第5个Text("this is test 5")开始引发溢出时,用省略号替代后续所有内容。

期望效果

期望效果

当前问题

屏幕宽度不足时,Row会出现水平溢出报错,效果如下:
当前结果

已尝试代码

return const MaterialApp(
  home: Scaffold(
    body: Center(
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text("this is test 1"),
          Icon(
            Icons.circle,
            size: 5,
          ),
          Text("this is test 2"),
          Icon(
            Icons.circle,
            size: 5,
          ),
          Text("this is test 3"),
          Icon(
            Icons.circle,
            size: 5,
          ),
          Text("this is test 4"),
          Icon(
            Icons.circle,
            size: 5,
          ),
          Text("this is test 5"),
          Icon(
            Icons.circle,
            size: 5,
          ),
          Text("this is test 6"),
          Icon(
            Icons.circle,
            size: 5,
          ),
        ],
      ),
    ),
  ),
);

解决方案

可以通过LayoutBuilder获取父容器的可用宽度,逐个计算子组件的宽度,当累计宽度加上省略号宽度超过可用空间时,停止添加后续子组件并插入省略号。示例代码如下:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(
          child: ResponsiveRowWithEllipsis(),
        ),
      ),
    );
  }
}

class ResponsiveRowWithEllipsis extends StatelessWidget {
  const ResponsiveRowWithEllipsis({super.key});

  @override
  Widget build(BuildContext context) {
    // 定义所有需要展示的子组件
    final List<Widget> originalChildren = [
      const Text("this is test 1"),
      const Icon(Icons.circle, size: 5),
      const Text("this is test 2"),
      const Icon(Icons.circle, size: 5),
      const Text("this is test 3"),
      const Icon(Icons.circle, size: 5),
      const Text("this is test 4"),
      const Icon(Icons.circle, size: 5),
      const Text("this is test 5"),
      const Icon(Icons.circle, size: 5),
      const Text("this is test 6"),
      const Icon(Icons.circle, size: 5),
    ];

    return LayoutBuilder(
      builder: (context, constraints) {
        double totalUsedWidth = 0;
        final List<Widget> displayChildren = [];
        final textScaleFactor = MediaQuery.of(context).textScaleFactor;

        // 计算省略号的宽度
        final ellipsisPainter = TextPainter(
          text: const TextSpan(text: "..."),
          maxLines: 1,
          textScaleFactor: textScaleFactor,
          textDirection: TextDirection.ltr,
        )..layout();
        final ellipsisWidth = ellipsisPainter.width;

        // 遍历子组件,筛选能显示的部分
        for (final child in originalChildren) {
          double childWidth = 0;

          // 计算不同类型子组件的宽度
          if (child is Text) {
            final textPainter = TextPainter(
              text: TextSpan(text: child.data, style: child.style),
              maxLines: 1,
              textScaleFactor: textScaleFactor,
              textDirection: TextDirection.ltr,
            )..layout();
            childWidth = textPainter.width;
          } else if (child is Icon) {
            childWidth = child.size;
          }

          // 预留子组件间距和省略号宽度,判断是否还能容纳当前子组件
          const double itemSpacing = 8; // 子组件间的间距,可自行调整
          if (totalUsedWidth + childWidth + itemSpacing + ellipsisWidth > constraints.maxWidth) {
            displayChildren.add(const Text("..."));
            break;
          }

          displayChildren.add(child);
          totalUsedWidth += childWidth + itemSpacing;
        }

        return Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: displayChildren,
        );
      },
    );
  }
}

代码说明

  1. 使用LayoutBuilder获取当前Row的可用宽度,确保计算基于实际可用空间。
  2. 逐个计算每个子组件的宽度,针对Text和Icon组件做了专门的宽度计算逻辑,其他类型组件可自行扩展。
  3. 预留了子组件间的间距和省略号的宽度,当剩余空间不足以容纳当前子组件+省略号时,就停止添加后续子组件,插入省略号。
  4. 最终将筛选后的子组件和省略号放入Row中,实现不换行的溢出省略效果。

内容的提问来源于stack exchange,提问作者Bart Van de Veire

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 14:24:54