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

Flutter自定义StrokeText组件溢出时阴影仅在省略号显示问题

描边文本组件溢出截断时阴影丢失问题原因

涉及代码

如下为基于TextShadow实现的文本描边自定义组件:

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

@immutable
class StrokeText extends StatelessWidget {
  final String text;
  final Color color;
  final Color strokeColor;
  final double strokeWidth;
  final TextStyle? style;
  final TextOverflow? overflow;

  const StrokeText(
    this.text, {
    Key? key,
    this.color = Colors.white,
    this.strokeColor = Colors.black,
    this.strokeWidth = 1,
    this.style,
    this.overflow,
  }) : super(key: key);

  List<Shadow> outlinedText({
    double strokeWidth = 2,
    Color strokeColor = Colors.black,
    int precision = 5,
  }) {
    Set<Shadow> result = {};
    for (int x = 1; x < strokeWidth + precision; x++) {
      for (int y = 1; y < strokeWidth + precision; y++) {
        double offsetX = x.toDouble();
        double offsetY = y.toDouble();
        result.add(Shadow(offset: Offset(-strokeWidth / offsetX, -strokeWidth / offsetY), color: strokeColor));
        result.add(Shadow(offset: Offset(-strokeWidth / offsetX, strokeWidth / offsetY), color: strokeColor));
        result.add(Shadow(offset: Offset(strokeWidth / offsetX, -strokeWidth / offsetY), color: strokeColor));
        result.add(Shadow(offset: Offset(strokeWidth / offsetX, strokeWidth / offsetY), color: strokeColor));
      }
    }
    return result.toList();
  }

  @override
  Widget build(BuildContext context) {
    return Text(
      text,
      overflow: overflow,
      style: TextStyle(
        fontSize: style?.fontSize,
        fontWeight: style?.fontWeight,
        fontFamily: style?.fontFamily,
        height: style?.height,
        wordSpacing: style?.wordSpacing,
        color: color,
        shadows: outlinedText(
          strokeColor: strokeColor,
          strokeWidth: strokeWidth,
        ),
      ),
    );
  }
}

问题表现

该组件通过多方向偏移的阴影拼接实现文字描边,文本长度未超出布局约束时效果正常;当文本触发溢出截断(如显示末尾省略号)时,截断位置前的文本描边阴影全部消失,仅末尾省略号保留完整阴影效果。

产生原因

该问题由Flutter框架文本渲染的固有逻辑导致,与阴影生成逻辑无关:

  • 当Text组件配置了溢出截断规则时,渲染管线会先计算当前布局约束下可容纳的文本范围,超出范围的内容会被判定为裁剪区域外内容,直接跳过包括TextShadow在内的所有样式绘制流程。
  • 多阴影模拟描边的核心原理是在每个字形的四周多个偏移位置绘制同色阴影,拼接成连续的描边效果;这些向外偏移的阴影只要落在框架判定的有效绘制区域外,就会被硬裁剪丢弃,最终表现为截断前的文本无描边。
  • 截断位置的省略号是框架单独插入的独立渲染元素,其阴影计算以自身位置为基准,不受前面文本的裁剪逻辑影响,因此只有省略号上能看到完整描边。

内容的提问来源于stack exchange,提问作者anonymous-dev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 05:18:20