FlutterのTextで文字列を表示する際、日本語の折り返し位置が思ったようにならないと感じたことはないでしょうか?
特に、半角スペースで区切られた日本語の文字列を表示すると、英語のように自然な単位で折り返されず、単語の途中で折り返されてしまうことがあります。
今回は、この問題を(力技で)いい感じに見せる方法を紹介します。
Textで発生する日本語折り返しの問題
例えば、以下の文字列をTextで表示した場合の挙動を見てみましょう。
Sapporo Tokyo Nagoya Osaka Fukuoka
さっぽろ とうきょう なごや おおさか ふくおか
このように、英語では単語ごとに自動で折り返されますが、日本語では単語の途中で折り返されてしまいます。
ゼロ幅非改行文字(\ufeff)を使って解決する
この問題を解決するためのアプローチとして、ゼロ幅非改行文字(\ufeff)を使います。
ゼロ幅非改行文字は、見た目に表示されず、改行を抑制する効果があります。
つまり、半角スペース以外の文字の間に\ufeffを入れることで、
半角スペースの位置でしか改行が起こらないようにすることが可能です。
実際に試してみましょう。
import 'package:flutter/material.dart';
class FixedWrapSample extends StatelessWidget {
const FixedWrapSample({super.key});
String applyNoBreak(String text) {
// 半角スペース以外の文字の間にゼロ幅非改行文字を挿入
return text.replaceAllMapped(
RegExp(r'(?<! )(?=.)'),
(Match match) => '\ufeff${match.group(0)}',
);
}
@override
Widget build(BuildContext context) {
const String text = 'さっぽろ とうきょう なごや おおさか ふくおか';
final String displayText = applyNoBreak(text);
return Scaffold(
appBar: AppBar(
title: const Text('Wrap Sample'),
centerTitle: true,
),
body: Container(
margin: const EdgeInsets.symmetric(horizontal: 64.0),
color: const Color(0xFFD7EBFC),
child: Text(
displayText,
style: const TextStyle(fontSize: 20),
),
),
);
}
}
何もしない状態では「なごや」の途中で折り返しが発生していましたが、
ゼロ幅非改行文字を挿入したことで「なごや」の手前で折り返しが発生するようになりました。
他の区切り文字への対応
この方法は半角スペース以外の文字にも対応可能です。
例えば、「、」や「・」などで区切りたい場合でも、正規表現を変更すれば対応することができます。
String applyNoBreak(String text, String delimiter) {
final String escapedDelimiter = RegExp.escape(delimiter);
return text.replaceAllMapped(
RegExp('(?<!$escapedDelimiter)(?=.)'),
(Match match) => '\ufeff${match.group(0)}',
);
}
注意点
この方法はあくまで「力技」なので、使用する場合は以下の点に注意が必要です。
- 文字列を加工してしまうため、Textに渡すデータに対してのみ適用する
-
\ufeffを大量に挿入するため、パフォーマンスへの影響を考慮する
これらの理由から、見た目を重視したい箇所に限定して使用することをおすすめします。
おわりに
Flutterの開発では欠かすことのできないTextで発生した問題の共有でした。
今回紹介した方法は一時的な回避策として使えると思うので、どうしても美しいレイアウトを保ちたい場面で活用してみてください。
株式会社ボトルキューブではFlutterを使ったお仕事を募集中です。
お問い合わせは下記リンク先のフォームからご連絡ください。


