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

如何在Flutter中实现如图所示的文本样式及内部阴影效果?

文本内部阴影效果示例

Flutter 文本添加内部阴影的解决方案

下面是几种可行的实现方案,你可以根据需求选择:

方法一:使用ShaderMask组件

这是最简洁的实现方式,通过渐变着色器配合混合模式,只在文本区域内生成阴影效果。

ShaderMask(
  shaderCallback: (bounds) => RadialGradient(
    center: Alignment.center,
    radius: 1.0,
    colors: [Colors.black.withOpacity(0.6), Colors.transparent],
    stops: const [0.5, 1.0],
  ).createShader(bounds),
  blendMode: BlendMode.dstIn,
  child: const Text(
    "INNER SHADOW",
    style: TextStyle(
      fontSize: 48,
      fontWeight: FontWeight.bold,
      color: Colors.white,
    ),
  ),
)

原理:径向渐变从文本中心的半透明黑色过渡到透明,BlendMode.dstIn让渐变仅作用于文本的像素区域,模拟出内部阴影的视觉效果。你可以调整渐变的参数(比如方向、颜色、停止点)来改变阴影的样式。

方法二:自定义CustomPaint绘制

如果需要更精细控制阴影的偏移、模糊程度等,可以用自定义绘制实现:

CustomPaint(
  painter: _InnerShadowTextPainter(
    text: "INNER SHADOW",
    textStyle: const TextStyle(
      fontSize: 48,
      fontWeight: FontWeight.bold,
      color: Colors.white,
    ),
    shadowColor: Colors.black.withOpacity(0.5),
    shadowOffset: const Offset(2, 2),
  ),
  size: const Size(double.infinity, 100),
)

对应的自定义Painter类:

class _InnerShadowTextPainter extends CustomPainter {
  final String text;
  final TextStyle textStyle;
  final Color shadowColor;
  final Offset shadowOffset;

  _InnerShadowTextPainter({
    required this.text,
    required this.textStyle,
    required this.shadowColor,
    required this.shadowOffset,
  });

  @override
  void paint(Canvas canvas, Size size) {
    // 先绘制偏移的阴影文本
    final shadowSpan = TextSpan(text: text, style: textStyle.copyWith(color: shadowColor));
    final shadowPainter = TextPainter(
      text: shadowSpan,
      textAlign: TextAlign.center,
      textDirection: TextDirection.ltr,
    )..layout(minWidth: size.width, maxWidth: size.width);
    shadowPainter.paint(canvas, shadowOffset);

    // 裁剪出原文本的区域,只保留该区域内的内容
    final textPath = shadowPainter.getBounds().toPath();
    canvas.save();
    canvas.clipPath(textPath);
    
    // 绘制原文本,覆盖阴影,仅保留文本内部的阴影部分
    final originalSpan = TextSpan(text: text, style: textStyle);
    final originalPainter = TextPainter(
      text: originalSpan,
      textAlign: TextAlign.center,
      textDirection: TextDirection.ltr,
    )..layout(minWidth: size.width, maxWidth: size.width);
    originalPainter.paint(canvas, Offset.zero);
    
    canvas.restore();
  }

  @override
  bool shouldRepaint(covariant _InnerShadowTextPainter oldDelegate) {
    return text != oldDelegate.text ||
        textStyle != oldDelegate.textStyle ||
        shadowColor != oldDelegate.shadowColor ||
        shadowOffset != oldDelegate.shadowOffset;
  }
}

方法三:Stack+ClipPath组合

通过层叠文本和裁剪的方式实现内部阴影:

Stack(
  alignment: Alignment.center,
  children: [
    // 底层的阴影文本
    const Text(
      "INNER SHADOW",
      style: TextStyle(
        fontSize: 48,
        fontWeight: FontWeight.bold,
        color: Colors.black38,
      ),
    ),
    // 用原文本的形状裁剪,只保留阴影在文本内部的部分
    ClipPath(
      clipper: _TextClipper(
        text: "INNER SHADOW",
        textStyle: const TextStyle(
          fontSize: 48,
          fontWeight: FontWeight.bold,
        ),
      ),
      child: const Text(
        "INNER SHADOW",
        style: TextStyle(
          fontSize: 48,
          fontWeight: FontWeight.bold,
          color: Colors.white,
        ),
      ),
    ),
  ],
)

对应的自定义裁剪器:

class _TextClipper extends CustomClipper<Path> {
  final String text;
  final TextStyle textStyle;

  _TextClipper({required this.text, required this.textStyle});

  @override
  Path getClip(Size size) {
    final textPainter = TextPainter(
      text: TextSpan(text: text, style: textStyle),
      textAlign: TextAlign.center,
      textDirection: TextDirection.ltr,
    )..layout(minWidth: size.width, maxWidth: size.width);
    return textPainter.getBounds().toPath();
  }

  @override
  bool shouldReclip(covariant _TextClipper oldClipper) {
    return text != oldClipper.text || textStyle != oldClipper.textStyle;
  }
}

内容的提问来源于stack exchange,提问作者Ahmed Iqbal teli

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 20:42:44