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

Flutter可展开收起文本组件 收起时底部模糊效果未恢复问题

问题根因

遮罩无法恢复是颜色赋值逻辑写错了:

  • 初始时fadeStrong、fadeWeak是半透黑色,收起状态遮罩正常
  • 第一次点展开,你直接把两个颜色变量改成了透明值,这时候变量存的已经不是原来的半透黑了
  • 第二次点收起,判断分支写的是hiddenText ? fadeStrong = fadeStrong,等于把已经是透明的值又赋给自己,根本没重置回初始颜色,遮罩当然出不来

另外你现在叠两个纯色黑块的实现不算真模糊,视觉生硬;还有拿字符数和像素高度比着截断文本,单位不统一,截断位置会乱。

修复代码

直接去掉手动修改颜色变量的逻辑,遮罩显隐完全跟着hiddenText状态走,同时把纯色遮罩换成渐变效果更自然,修复后完整代码如下:

import 'dart:ui';
import 'package:flutter/material.dart';

class ExpandableText extends StatefulWidget {
  final String text;
  const ExpandableText({Key? key, required this.text}) : super(key: key);

  @override
  State<ExpandableText> createState() => _ExpandableTextState();
}

class _ExpandableTextState extends State<ExpandableText> {
  late String firstHalf;
  late String secondHalf;
  bool hiddenText = true;
  final double textHeight = 180;
  // 固定遮罩初始颜色,设为final禁止运行时修改
  final Color fadeStrong = Colors.black.withOpacity(0.8);
  final Color fadeWeak = Colors.black.withOpacity(0.6);

  @override
  void initState() {
    super.initState();
    // 注:原逻辑拿字符数和像素高度对比单位不统一,后续可通过LayoutBuilder+TextPainter计算真实截断位置,本次先保留原有逻辑解决遮罩问题
    if (widget.text.length > textHeight) {
      firstHalf = widget.text.substring(0, textHeight.toInt());
      secondHalf = widget.text.substring(textHeight.toInt() + 1, widget.text.length);
    } else {
      firstHalf = widget.text;
      secondHalf = "";
    }
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Container(
          child: secondHalf.isEmpty
              ? Text(
                  firstHalf,
                  style: const TextStyle(color: Colors.white),
                )
              : Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      hiddenText ? ("$firstHalf...") : (firstHalf + secondHalf),
                      style: const TextStyle(color: Colors.white, height: 1.5),
                    ),
                    InkWell(
                      onTap: () {
                        setState(() {
                          hiddenText = !hiddenText;
                        });
                      },
                      child: Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          Text(
                            hiddenText ? 'Read more' : 'Read less',
                            style: const TextStyle(color: Colors.blue),
                          ),
                          Icon(
                            hiddenText ? Icons.arrow_drop_down : Icons.arrow_drop_up_outlined,
                            color: Colors.blue,
                          )
                        ],
                      ),
                    )
                  ],
                ),
        ),
        // 仅在收起+文本需要截断时渲染遮罩,展开时直接从组件树移除
        if (hiddenText && secondHalf.isNotEmpty)
          Positioned(
            bottom: 40, // 位置避开下方的展开/收起按钮
            left: 0,
            right: 0,
            height: 40,
            // 不需要真模糊效果可以删掉ClipRect和BackdropFilter层,仅保留渐变容器即可
            child: ClipRect(
              child: BackdropFilter(
                filter: ImageFilter.blur(sigmaX: 0.8, sigmaY: 0.8),
                child: Container(
                  decoration: BoxDecoration(
                    gradient: LinearGradient(
                      begin: Alignment.topCenter,
                      end: Alignment.bottomCenter,
                      colors: [
                        Colors.black.withOpacity(0),
                        Colors.black.withOpacity(0.6),
                        Colors.black.withOpacity(0.8),
                      ],
                    ),
                  ),
                ),
              ),
            ),
          ),
      ],
    );
  }
}
修复说明
  • 把颜色变量设为final常量,不再在点击事件里手动修改,从根源避免变量值被改乱
  • 遮罩层通过条件判断渲染,展开时直接移除组件,不用靠改透明度隐藏
  • 可选加了BackdropFilter实现真正的文字模糊效果,搭配线性渐变过渡比原来的两个硬黑条自然很多
  • 修正了Column默认交叉对齐问题,避免文本和按钮布局错位
效果参考

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:03:27