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
相关产品推荐
相关产品推荐

