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

Flutter中textAlign: justify对日文无效,如何调整行字符间距?

Flutter 中日文文本两端对齐(调整字符间距)实现方案

Flutter 默认的 TextAlign.justify 仅对英语这类空格分隔的语言生效,日文这类无空格分隔的语言无法直接通过该属性实现两端对齐。要达到每行文本撑满容器宽度的效果,可通过以下两种方案实现:

方案1:自定义动态计算字符间距

通过计算每行文本与容器宽度的差值,将额外空间平均分配到字符之间,动态调整 letterSpacing 属性,让非最后一行的文本撑满宽度。

实现代码

import 'package:flutter/material.dart';
import 'dart:ui' as ui;

class JustifiedJapaneseText extends StatelessWidget {
  final String text;
  final TextStyle style;
  final double containerWidth;

  const JustifiedJapaneseText({
    super.key,
    required this.text,
    required this.style,
    required this.containerWidth,
  });

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        // 先计算文本的分行情况
        final textPainter = TextPainter(
          text: TextSpan(text: text, style: style),
          textDirection: TextDirection.ltr,
          maxLines: null,
        )..layout(maxWidth: containerWidth);

        List<String> lines = [];
        int currentPos = 0;
        while (currentPos < text.length) {
          final lineEndPos = textPainter.getPositionForOffset(Offset(containerWidth, 0)).offset;
          lines.add(text.substring(currentPos, lineEndPos));
          currentPos = lineEndPos;
        }

        // 处理每行的字符间距,最后一行保持原样式
        final List<Widget> justifiedWidgets = [];
        for (int i = 0; i < lines.length; i++) {
          final line = lines[i];
          if (i == lines.length - 1) {
            justifiedWidgets.add(Text(line, style: style));
            continue;
          }

          final linePainter = TextPainter(
            text: TextSpan(text: line, style: style),
            textDirection: TextDirection.ltr,
          )..layout();
          final extraSpace = containerWidth - linePainter.width;
          final charCount = line.length;
          // 计算每个字符间需要添加的间距
          final spacing = charCount > 1 ? extraSpace / (charCount - 1) : 0;

          justifiedWidgets.add(
            Text(
              line,
              style: style.copyWith(letterSpacing: spacing),
            ),
          );
        }

        return Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: justifiedWidgets,
        );
      },
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: JustifiedJapaneseText(
          text: 'よそは時間そんなにどんな発展家というのの時を移れですです。断然今度に反対界はもしその話ですただけへするて行くでをは独立知れませませて、それだけには合っますたありた。文学へ思うないのはとうてい一番でよほどらしくませまし。ようやくネルソンさんに干渉三つまだ満足にできるまし態度同じ主意どこか発展にというご関係たなうですて、このほかは私か言い方見込みがするから、三宅さんの訳を権力のそれにちょうどお注文となって私教師にお腐敗がしようにもう実お尋ねを読みなけれませて、どうもとうとう発展をなりたていたのをしませた。すなわちもっともお画にするのはたった不愉快と知らたば、その落がは込み入っなとに対して個人に入っていでたい。同じため盲目の日その個人も私中を減っごとくかと久原さんに仕上るありです、学校の時分たとい',
          style: const TextStyle(fontSize: 16),
          containerWidth: MediaQuery.of(context).size.width - 32,
        ),
      ),
    );
  }
}

方案2:借助第三方排版包

可以使用专门处理东亚文本排版的第三方包(如专注于文本布局的定制化包),这类包通常内置了中日文两端对齐的逻辑,能省去手动计算的步骤,但需要额外引入依赖并配置。

注意事项

  • 自定义计算方案中,可根据需求优化逻辑,比如避免在标点符号前后分配过大间距,提升排版美观度。
  • 如果文本包含手动换行符,需要提前处理分行逻辑,避免计算出错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 18:03:27