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

在Flutter应用中为Google字体Inter添加描边时线条重叠问题求助

在Flutter应用中为Google字体Inter添加描边时线条重叠问题求助

嘿,我之前也踩过这个坑!给Inter字体加描边的时候,像A这种有交叉笔画的字母特别容易出现线条重叠的情况,主要是因为Flutter默认的文本描边是直接对字体轮廓进行描边,而有些字体的轮廓路径在交叉处处理得比较紧凑,就会出现重叠。给你分享两个亲测有效的解决方法:

方法一:用Stack叠加偏移文本模拟描边(简单易上手)

这个方法思路很直接:先画几层偏移后的深色文本当描边,再在上面叠一层正常的填充文本。这样既能实现描边效果,又能避开字体轮廓的重叠问题。

修改你的SplashText代码试试:

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

  @override
  Widget build(BuildContext context) {
    const targetText = "YOUR TEXT HERE";
    const strokeWidth = 2.0;
    const strokeColor = Colors.black;
    const fillColor = Colors.white;
    const textSize = 48.0;

    return Row(
      children: [
        Expanded(
          child: SingleChildScrollView(
            child: Stack(
              alignment: Alignment.center,
              children: [
                // 四个方向偏移的描边文本
                Transform.translate(
                  offset: Offset(-strokeWidth, 0),
                  child: Text(
                    targetText,
                    style: TextStyle(
                      fontFamily: 'Inter',
                      fontSize: textSize,
                      color: strokeColor,
                    ),
                  ),
                ),
                Transform.translate(
                  offset: Offset(strokeWidth, 0),
                  child: Text(
                    targetText,
                    style: TextStyle(
                      fontFamily: 'Inter',
                      fontSize: textSize,
                      color: strokeColor,
                    ),
                  ),
                ),
                Transform.translate(
                  offset: Offset(0, -strokeWidth),
                  child: Text(
                    targetText,
                    style: TextStyle(
                      fontFamily: 'Inter',
                      fontSize: textSize,
                      color: strokeColor,
                    ),
                  ),
                ),
                Transform.translate(
                  offset: Offset(0, strokeWidth),
                  child: Text(
                    targetText,
                    style: TextStyle(
                      fontFamily: 'Inter',
                      fontSize: textSize,
                      color: strokeColor,
                    ),
                  ),
                ),
                // 可选:加上四个对角线偏移,让描边更圆润
                Transform.translate(
                  offset: Offset(-strokeWidth, -strokeWidth),
                  child: Text(
                    targetText,
                    style: TextStyle(
                      fontFamily: 'Inter',
                      fontSize: textSize,
                      color: strokeColor,
                    ),
                  ),
                ),
                Transform.translate(
                  offset: Offset(strokeWidth, -strokeWidth),
                  child: Text(
                    targetText,
                    style: TextStyle(
                      fontFamily: 'Inter',
                      fontSize: textSize,
                      color: strokeColor,
                    ),
                  ),
                ),
                Transform.translate(
                  offset: Offset(-strokeWidth, strokeWidth),
                  child: Text(
                    targetText,
                    style: TextStyle(
                      fontFamily: 'Inter',
                      fontSize: textSize,
                      color: strokeColor,
                    ),
                  ),
                ),
                Transform.translate(
                  offset: Offset(strokeWidth, strokeWidth),
                  child: Text(
                    targetText,
                    style: TextStyle(
                      fontFamily: 'Inter',
                      fontSize: textSize,
                      color: strokeColor,
                    ),
                  ),
                ),
                // 最上层的填充文本
                Text(
                  targetText,
                  style: TextStyle(
                    fontFamily: 'Inter',
                    fontSize: textSize,
                    color: fillColor,
                  ),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

优点:代码改动小,不用自定义组件;缺点:描边太粗时可能有点模糊,大量文本场景下性能略逊。

方法二:用CustomPaint手动绘制描边(精准解决重叠)

这个方法是直接操作文本的路径,通过设置画笔的strokeJoin为圆角,从根源上避免笔画交叉处的重叠问题,效果更专业。

先写一个自定义的描边文本组件:

class StrokedText extends StatelessWidget {
  final String text;
  final double fontSize;
  final Color strokeColor;
  final double strokeWidth;
  final Color fillColor;
  final String fontFamily;

  const StrokedText({
    super.key,
    required this.text,
    required this.fontSize,
    required this.strokeColor,
    required this.strokeWidth,
    required this.fillColor,
    required this.fontFamily,
  });

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: _StrokedTextPainter(
        text: text,
        fontSize: fontSize,
        strokeColor: strokeColor,
        strokeWidth: strokeWidth,
        fillColor: fillColor,
        fontFamily: fontFamily,
      ),
      child: SizedBox(
        width: double.infinity,
        child: Center(
          // 透明文本占位,保证布局正确
          child: Text(
            text,
            style: TextStyle(
              fontSize: fontSize,
              fontFamily: fontFamily,
              color: Colors.transparent,
            ),
          ),
        ),
      ),
    );
  }
}

class _StrokedTextPainter extends CustomPainter {
  final String text;
  final double fontSize;
  final Color strokeColor;
  final double strokeWidth;
  final Color fillColor;
  final String fontFamily;

  _StrokedTextPainter({
    required this.text,
    required this.fontSize,
    required this.strokeColor,
    required this.strokeWidth,
    required this.fillColor,
    required this.fontFamily,
  });

  @override
  void paint(Canvas canvas, Size size) {
    // 创建文本绘制器
    final textPainter = TextPainter(
      text: TextSpan(
        text: text,
        style: TextStyle(
          fontSize: fontSize,
          fontFamily: fontFamily,
        ),
      ),
      textDirection: TextDirection.ltr,
    )..layout(minWidth: size.width, maxWidth: size.width);

    // 计算文本居中偏移
    final offset = Offset(
      (size.width - textPainter.width) / 2,
      (size.height - textPainter.height) / 2,
    );

    // 描边画笔:设置圆角连接避免重叠
    final strokePaint = Paint()
      ..color = strokeColor
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..strokeJoin = StrokeJoin.round;

    // 先画描边
    textPainter.paint(canvas, offset, paint: strokePaint);

    // 填充画笔
    final fillPaint = Paint()
      ..color = fillColor
      ..style = PaintingStyle.fill;

    // 再画填充文本
    textPainter.paint(canvas, offset, paint: fillPaint);
  }

  @override
  bool shouldRepaint(covariant _StrokedTextPainter oldDelegate) {
    // 只有当参数变化时才重绘
    return oldDelegate.text != text ||
        oldDelegate.fontSize != fontSize ||
        oldDelegate.strokeColor != strokeColor ||
        oldDelegate.strokeWidth != strokeWidth ||
        oldDelegate.fillColor != fillColor ||
        oldDelegate.fontFamily != fontFamily;
  }
}

然后在你的SplashText里使用这个组件:

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

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(
          child: SingleChildScrollView(
            child: StrokedText(
              text: "YOUR TEXT HERE",
              fontSize: 48,
              strokeColor: Colors.black,
              strokeWidth: 2.0,
              fillColor: Colors.white,
              fontFamily: 'Inter',
            ),
          ),
        ),
      ],
    );
  }
}

这个方法的优势在于,strokeJoin: StrokeJoin.round会让笔画交叉处的描边变得圆润,彻底解决重叠问题,而且性能更好,适合各种描边粗细的场景。

最后别忘了确认你的pubspec.yaml里已经正确配置了Inter字体:

fonts:
  - family: Inter
    fonts:
      - asset: fonts/Inter-Regular.ttf
      # 如果用到其他字重,比如粗体,记得添加对应文件
      - asset: fonts/Inter-Bold.ttf
        weight: 700

备注:内容来源于stack exchange,提问作者user23331216

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 18:02:57