web-dev-qa-db-ja.com

Flutterの縦書きウィジェット

TextDirection ドキュメントは言う:

Flutterは、右から左または左から右の書き込み方向を使用しているかどうかに関係なく、世界で現在使用されている言語で書かれたアプリケーションのニーズに対応するように設計されています。 Flutterは、縦書きテキストやboustrophedonテキストなど、他の書き込みモードをサポートしていません。これらはコンピュータプログラムではほとんど使用されないためです。 (強調を追加)

Flutterは縦書きテキストをサポートしないだけでなく、将来的には正式にサポートされなくなります。これは初期の設計決定でした( ここ および ここ を参照)。

それでも、今日の垂直スクリプトのサポートは実際に使用されています。特定の 中国語と日本語 の使用に加えて、 伝統的なモンゴル語の​​スクリプト はそれを必要とします。このスクリプトは、内モンゴルのコンピュータープログラムで非常に一般的に使用されています( exampleexampleexampleexample 、- )。

上から下に書かれ、行は左から右に折り返されます。

enter image description here

さらに、絵文字とCJK文字は、垂直に表示されたときに向きを保持します(絶対に必要というわけではありませんが、推奨されます)。下の画像では、上の段落が現在の実装を示し、下の段落が正しい垂直方向のレンダリングを示しています。

enter image description here

// sample text
ᠨᠢᠭᠡ ᠬᠣᠶᠠᠷ ᠭᠣᠷᠪᠠ ᠳᠥᠷᠪᠡ ᠲᠠᠪᠤ ᠵᠢᠷᠭᠤᠭ᠎ᠠ ᠳᠣᠯᠣᠭ᠎ᠠ ᠨᠠ‍ᠢᠮᠠ ᠶᠢᠰᠦ ᠠᠷᠪᠠ one two three four five six seven eight nine ten ????????汉字 한국어 モンゴル語 English? ᠮᠣᠩᠭᠣᠯ︖

Flutterは垂直スクリプトをサポートしていないため、ゼロから実装する必要があります。実際のテキストのレイアウトとペイントはすべて、Flutterエンジンで LibTxt を使用して行われるため、変更できません。

上から下に垂直のテキストウィジェットを作成するにはどうすればよいでしょうか。

更新

私はまだ答えを探しています。レミの答えは単一行のテキストには適していますが、複数行のテキストには機能しません。

私は現在、3つの異なる解決策を研究しています。

  • RichTextウィジェットと同様のカスタムStatelessWidgetをサポートするRenderObjectサブクラス(または RenderParagraph サブクラス)を作成します。
  • CustomPaintウィジェットを使用する
  • ListView(テキスト行ごとに1行)、テキストウィジェット、およびWidgetSpansの複合ウィジェットを作成します。

それらのすべては、テキストの測定、レイアウト、および行のリストの取得を伴います。

別のアップデート

私は現在、RichTextとRenderParagraphを模倣するカスタムウィジェットとレンダリングオブジェクトの作成に傾いています。内部では、RenderParagraphはTextPainterを使用してテキストをレイアウトおよびペイントします。今の私の問題は、TextPainterが基盤となるSkia LibTxtライブラリーと密結合していることです。ここで実際のレイアウトとペイントがすべて行われます。デフォルトのltrとrtl以外のテキストをレイアウトすることは、大きな問題であることが判明しています。

さらに別のアップデート

受け入れられた回答は、この質問で述べた基準を満たしています。短期的なニーズには対応できると思います。テキストスタイルの適用など、いくつかの予約がありますが、さらにテストを行う必要があります。長期的には、カスタムのテキストレイアウトとペイントを引き続き試みる可能性があります。

17
Suragch

このソリューションは、フレックスボックスレイアウトに基づいています。文字列を単語のリストに変換し、垂直に回転したテキストウィジェットに配置します。これらは、WrapウィジェットをAxis.verticalに設定してレイアウトされます。折り返しウィジェットは、折り返す必要がある単語を次の列に配置することで自動的に処理します。

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Wrap(
          direction: Axis.vertical,
          children: _getWords(),
        ),
      ),
    );
  }

  List<Widget> _getWords() {
    const text =
        "That's all ???????? 12345 One Two Three Four Five ᠸᠢᠺᠢᠫᠧᠳᠢᠶᠠ᠂ ᠴᠢᠯᠦᠭᠡᠲᠦ ᠨᠡᠪᠲᠡᠷᠬᠡᠢ ᠲᠣᠯᠢ ᠪᠢᠴᠢᠭ ᠪᠣᠯᠠᠢ᠃";
    var emoji = RegExp(r"([\u2200-\u3300]|[\uD83C-\uD83E].)");
    List<Widget> res = [];
    var words = text.split(" ");
    for (var Word in words) {
      var matches = emoji.allMatches(Word);
      if (matches.isEmpty) {
        res.add(RotatedBox(quarterTurns: 1, child: Text(Word + ' ')));
      } else {
        var parts = Word.split(emoji);
        int i = 0;
        for (Match m in matches) {
          res.add(RotatedBox(quarterTurns: 1, child: Text(parts[i++])));
          res.add(Text(m.group(0)));
        }
        res.add(RotatedBox(quarterTurns: 1, child: Text(parts[i] + ' ')));
      }
    }
    return res;
  }
}

enter image description here

10
Spatz

横向きのテキストはRotatedBoxを使用して可能です。これは、テキストを正しくラップするために十分です。

Row(
  children: <Widget>[
    RotatedBox(
      quarterTurns: 1,
      child: Text(sample),
    ),
    Expanded(child: Text(sample)),
    RotatedBox(
      quarterTurns: -1,
      child: Text(sample),
    ),
  ],
),

enter image description here

同様に、Flutterはテキスト内のインラインウィジェットをサポートするようになりました。これは、テキスト内のスマイリーを回転させるために使用できます。

RotatedBox(
  quarterTurns: 1,
  child: RichText(
    text: TextSpan(
      text: 'Hello World',
      style: DefaultTextStyle.of(context).style,
      children: [
        WidgetSpan(
          child: RotatedBox(quarterTurns: -1, child: Text('????')),
        )
      ],
    ),
  ),
),

enter image description here

10
Rémi Rousselet

すべての記号を180度回転させてカスタムフォントを作成する場合(ハードパーツ)、単純にtextDirectionTextDirection.rtl(右から左)に変更して回転させることができますテキストを4分の1ずつ(簡単でもありません)。

2
Spatz

最終的に、テキストレンダリングを処理するカスタムウィジェットを作成しました。この記事の執筆時点では、絵文字とCJK文字は正しく回転しませんが、向きと行の折り返しを処理します。

これは簡単な作業ではありませんでしたが、柔軟性があります。他の回答があなたのニーズを満たさない場合、この質問への他の訪問者は同様のパターンに従うことができます。

Flutterでのテキストのレンダリングをより詳細に制御したい場合は、 Flutterでの最初の失望 を読み、コメントを このGitHubの問題 に追加します。

0
Suragch