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

Flutter:如何用letterSpacing实现不同长度文本统一字间距?

用letterSpacing+maxLines=1实现不同长度文本的均等字间距

需求

要实现这样的布局效果:两行长度不同的文本,字符之间均匀分布并填满整行,示例如下:

H   E   L    L   O
H EL L O W O R L D

目前我已经通过Row组件配合MainAxisAlignment.spaceBetween实现了该效果,但想改用letterSpacing属性结合maxLines=1的方式来实现,先贴出现有实现代码:

Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: 'HELLO'
      .characters
      .map((e) => Text(e,
          style: GoogleFonts.poppins(
            fontSize: 30,
            fontWeight: FontWeight.bold,
          )))
      .toList(),
),
Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: 'HELLO WORLD'
      .characters
      .map((e) => Text(e,
          style: GoogleFonts.poppins(
            fontSize: 30,
            fontWeight: FontWeight.bold,
          )))
      .toList(),
),

实现思路&代码

用letterSpacing实现的核心是动态计算出刚好让文本撑满指定宽度的字间距值——因为letterSpacing是固定的字符间距离,而我们需要字符均匀铺满整行,所以得根据文本长度和容器宽度反向推导间距。

直接上可复用的实现代码:

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

// 封装成组件方便复用
class EqualSpacingText extends StatelessWidget {
  final String text;
  final double fontSize;
  final FontWeight fontWeight;
  final double containerWidth;

  const EqualSpacingText({
    super.key,
    required this.text,
    required this.fontSize,
    required this.fontWeight,
    required this.containerWidth,
  });

  @override
  Widget build(BuildContext context) {
    // 获取目标文本样式
    final textStyle = GoogleFonts.poppins(
      fontSize: fontSize,
      fontWeight: fontWeight,
    );
    // 用TextPainter测量单个字符的实际宽度(不同字体/字号的字符宽度有差异,必须实测)
    final textPainter = TextPainter(
      text: TextSpan(text: 'A', style: textStyle),
      textDirection: TextDirection.ltr,
    )..layout();
    final singleCharWidth = textPainter.width;

    // 计算所有字符的总宽度
    final totalCharsWidth = singleCharWidth * text.length;
    // 容器剩余宽度就是所有字符间隙需要分摊的总宽度
    final totalSpacing = containerWidth - totalCharsWidth;
    // 字符间隙数为「字符数-1」,算出每个间隙的字间距
    final letterSpacing = text.length > 1 ? totalSpacing / (text.length - 1) : 0;

    return SizedBox(
      width: containerWidth,
      child: Text(
        text,
        maxLines: 1, // 强制单行,避免换行破坏布局
        style: textStyle.copyWith(letterSpacing: letterSpacing),
      ),
    );
  }
}

// 使用示例
class DemoPage extends StatelessWidget {
  const DemoPage({super.key});

  @override
  Widget build(BuildContext context) {
    // 取屏幕宽度,减去左右各20的边距作为文本容器宽度
    final containerWidth = MediaQuery.of(context).size.width - 40;

    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 20),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            EqualSpacingText(
              text: 'HELLO',
              fontSize: 30,
              fontWeight: FontWeight.bold,
              containerWidth: containerWidth,
            ),
            const SizedBox(height: 20),
            EqualSpacingText(
              text: 'HELLO WORLD',
              fontSize: 30,
              fontWeight: FontWeight.bold,
              containerWidth: containerWidth,
            ),
          ],
        ),
      ),
    );
  }
}

注意事项

  • 必须给文本容器设置固定宽度,否则无法计算出刚好撑满的字间距
  • 一定要用TextPainter测量字符宽度,不能凭经验估算,不同字体的字符宽度差异很大
  • 若文本只有单个字符,直接将letterSpacing设为0,避免出现计算异常
  • 必须加上maxLines=1,强制文本单行显示,防止换行破坏均匀分布的布局

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 04:48:18