1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Flutter小技集】TextSpanでforループ回して、間に「・」打ちたい時

Last updated at Posted at 2021-04-23

今日の主役

Flutterで同じ行に様々なフォントやスタイルを混在させるのに便利な**RichText**クラス

こいつ(RichText)に表示させる複数の文言をDBから配列で取得して、ループ処理でWidgetを生成して渡そうと思ってたんだけども、ちょっとつまづいたので備忘録含めて小技紹介です。

やりたかった事

簡単に言うと、

  • 表示したい文言が格納されてる配列を取得
  • それをループ処理でRichTextに渡し、描画させる

こんなイメージです⬇︎

それぞれの決済方法に下線を引き、その間に区切りの「・」を入れる。プラス現金払いをその他の決済方法と区別する為に「と現金払い」という風に「と」を頭に付けたい感じでした。

試した事

「・」や「と」をどのタイミングで打てば良いかはその文字列が何番目か知る必要があります。なので配列の値だけでなく、indexもくれるList<T>.generate()を使おう。(他にも色々書き方はあるので、それはまたどこかで触れたいと思います。)

それをいざchildrenのListに渡した結果、「List<TextSpan>なんて渡してくるんじゃないよ!TextSpanしか私は受けとんないよ!」と怒られてしまう。

ううう、でもindex使いたいからList.generate()がいいんですもの...

うまくいかない
final List<String> list = <String>['クレジットカード','交通系ICカード','現金払い'];

@override 
Widget build(BuildContext context){
   return Container(
      child: RichText(
        text: TextSpan(
         children: <TextSpan>[ // <TextSpan>しか受け取らないよ!
            List<InlineSpan>.generate(  // List<TextSpan>なんて渡してくるんじゃないよ!
                list.length,
                (int index){
                  return TextSpan(
                      children: <TextSpan> [
                        if(index != 0 && list[index] != '現金払い')
                          const TextSpan(text:'・'),
                        if(index != 0 && list[index] == '現金払い')
                          const TextSpan(text:'と'),
                        TextSpan(
                          text: list[index],
                          style: const TextStyle(
                            decoration: TextDecoration.underline,
                          ),
                        ),
                      ],
                  );
                },
              ),
            ],
         ),
       ),
    );
  }

結論:childrenプロパティに直で渡せ!

結論としてはchildrenに渡したList<TextSpan>の中で記述するのではなく、単純にchildrenに直で渡せば良かった。

ちなみにInlineSpanというのはTextSpanの親クラスになります。

うまくいく
final List<String> list = <String>['クレジットカード','交通系ICカード','現金払い'];

@override 
Widget build(BuildContext context){
   return Container(
      child: RichText(
        text: TextSpan(
         children: List<InlineSpan>.generate( // ⬅︎ ココ!直渡し
            list.length,
            (int index){
               return TextSpan(
                  children: <TextSpan> [
                    if(index != 0 && list[index] != '現金払い')
                      const TextSpan(text:'・'),
                    if(index != 0 && list[index] == '現金払い')
                      const TextSpan(text:'と'),
                    TextSpan(
                      text: list[index],
                      style: const TextStyle(
                        decoration: TextDecoration.underline,
                      ),
                    ),
                  ],
               );
             },
          ),
        ),
       ),
    );
  }

そしてもっとスマートな書き方

こちらの記事の誤りについてご指摘してくださった@kabochapoさんがよりスマートな書き方を教えてくださいました。ありがとうございます!

list.firstで配列の頭の値かを判別する事ができるのでそもそもindex無くても今回の要件は満たせる様です。それを使えばList.generate()で記述する必要がなくなるので、children配下のList内でfor文を回し、やりたかった事を達成できました!

スマート
  final List<String> list = <String>['クレジットカード', '交通系ICカード', '現金払い'];

  @override
  Widget build(BuildContext context) {
    return Container(
      child: RichText(
        text: TextSpan(
          children: <TextSpan>[
            for (String type in list) ...<TextSpan>[
              if (type != list.first && type != '現金払い')
                const TextSpan(text: '・'),
              if (type == list.first && type == '現金払い')
                const TextSpan(text: 'と'),
              TextSpan(
                text: type,
                style: const TextStyle(
                  decoration: TextDecoration.underline,
                ),
              ),
            ],
          ],
        ),
      ),
    );
  }

ベリースマート

参考

https://stackoverflow.com/questions/56947046/flutter-for-loop-to-generate-list-of-widgets
https://stackoverflow.com/questions/61922116/flutter-how-to-use-to-have-different-kind-of-widgets-in-for-loops

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?