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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 11:27:04