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

如何在Flutter中实现数字前置补0阴影的文本UI效果?

在Flutter中实现补位0带阴影的数字UI效果

要实现这种「补位0带阴影、实际数字无阴影」的效果,核心是把数字拆分为补位的0和实际有效数字两部分,分别给这两部分设置不同的文本样式即可。以下是两种实用的实现方案:

方案1:使用RichText组件(推荐,无额外布局嵌套)

通过RichText的TextSpan可以在同一段文本中混合不同样式,代码示例如下:

class ShadowLeadingZerosText extends StatelessWidget {
  final int number;
  final int totalLength; // 数字的总位数,比如示例中是4位
  final TextStyle zeroStyle;
  final TextStyle numberStyle;

  const ShadowLeadingZerosText({
    super.key,
    required this.number,
    this.totalLength = 4,
    TextStyle? zeroStyle,
    TextStyle? numberStyle,
  })  : zeroStyle = zeroStyle ?? TextStyle(
          fontSize: 24,
          color: Colors.black,
          shadows: const [
            Shadow(
              color: Colors.grey,
              offset: Offset(1, 1),
              blurRadius: 2,
            ),
          ],
        ),
        numberStyle = numberStyle ?? const TextStyle(
          fontSize: 24,
          color: Colors.black,
        );

  @override
  Widget build(BuildContext context) {
    // 把数字补位到指定总长度的字符串
    final numberStr = number.toString().padLeft(totalLength, '0');
    // 找到第一个非0字符的位置,拆分补位0和实际数字
    final firstNonZeroIndex = numberStr.indexOf(RegExp(r'[1-9]'));
    // 处理数字为0的特殊情况
    final leadingZeros = firstNonZeroIndex == -1 
        ? numberStr 
        : numberStr.substring(0, firstNonZeroIndex);
    final actualNumber = firstNonZeroIndex == -1 
        ? '' 
        : numberStr.substring(firstNonZeroIndex);

    return RichText(
      text: TextSpan(
        children: [
          // 补位0的文本段,带阴影样式
          TextSpan(text: leadingZeros, style: zeroStyle),
          // 实际数字的文本段,无阴影样式
          TextSpan(text: actualNumber, style: numberStyle),
        ],
      ),
    );
  }
}

使用方式:

// 数字28的情况,显示0028,前两个0带阴影
ShadowLeadingZerosText(number: 28),
// 数字5的情况,显示0005,前三个0带阴影
ShadowLeadingZerosText(number: 5),

方案2:使用Row组件(布局更直观)

如果觉得RichText的文本拼接不够直观,可以用Row将两个Text组件并排,分别对应补位0和实际数字:

class ShadowLeadingZerosRow extends StatelessWidget {
  final int number;
  final int totalLength;
  final TextStyle zeroStyle;
  final TextStyle numberStyle;

  const ShadowLeadingZerosRow({
    super.key,
    required this.number,
    this.totalLength = 4,
    TextStyle? zeroStyle,
    TextStyle? numberStyle,
  })  : zeroStyle = zeroStyle ?? TextStyle(
          fontSize: 24,
          color: Colors.black,
          shadows: const [
            Shadow(
              color: Colors.grey,
              offset: Offset(1, 1),
              blurRadius: 2,
            ),
          ],
        ),
        numberStyle = numberStyle ?? const TextStyle(
          fontSize: 24,
          color: Colors.black,
        );

  @override
  Widget build(BuildContext context) {
    final numberStr = number.toString().padLeft(totalLength, '0');
    final firstNonZeroIndex = numberStr.indexOf(RegExp(r'[1-9]'));
    final leadingZeros = firstNonZeroIndex == -1 
        ? numberStr 
        : numberStr.substring(0, firstNonZeroIndex);
    final actualNumber = firstNonZeroIndex == -1 
        ? '' 
        : numberStr.substring(firstNonZeroIndex);

    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        Text(leadingZeros, style: zeroStyle),
        Text(actualNumber, style: numberStyle),
      ],
    );
  }
}

关键逻辑说明

  1. 补位处理:用padLeft(totalLength, '0')把数字转换成指定长度的字符串,不足的部分左侧补0。
  2. 拆分字符串:通过正则找到第一个非0字符的位置,将字符串拆分为「补位0」和「实际数字」两部分。
  3. 样式区分:给补位0的文本设置包含shadows属性的样式,实际数字使用无阴影的样式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 23:47:28