FlutterでログUIを作ってみる

はじめに

こんにちは。エンジニアのSです。

今回はFlutterでツールアプリを開発するとき、情報を出力する際によくあるログUIの作り方を紹介したいと思います!

 

まず、ログUIっぽい簡単な文字表示のコードを書いてみます。

 

…

Column(

					crossAxisAlignment: CrossAxisAlignment.stretch,

                    children: [

                      const Text(“<動作ログ>”),

                      Container(

                          width: 500,

                          height: 170,

                          color: const Color.fromARGB(255, 226, 226, 226),

                          child: SingleChildScrollView(

                              child: Text(

                            "Hello World\nHogeHogeHogeHogeHoge\nHogeHogeHogeHoge\nHogeHogeHoge",

                            style: TextStyle(fontSize: 35),

                          )

                              )),

                    ],

),

…

はい、これで簡単に文字表示部分をスクロールできるようになりました!

 

文字を選択できるようにしたい

 

ですが、これだけではログにある文字を選択できないので、直感的にログ文字をコピーできないですね。

これは一般的に使われているTextクラスで、仕様上では選択できないからです。

選択できるようにしたいならば、SelectableTextクラスを置き換えるだけでできるようになります!

 

Column(

                    crossAxisAlignment: CrossAxisAlignment.stretch,

                    children: [

                      const Text(“<動作ログ>”),

                      Container(

                          width: 500,

                          height: 170,

                          color: const Color.fromARGB(255, 226, 226, 226),

                          child: SingleChildScrollView(

                              child: SelectableText(

                            "Hello World\nHogeHogeHogeHogeHoge\nHogeHogeHogeHoge\nHogeHogeHoge",

                            style: TextStyle(fontSize: 35),

                          )

                              )),

                    ],

),

ログの種類によって文字のスタイルを変更したい

しかし、このままだとログUI内全部の文字スタイルが統一されてしまいます。

特定のログを別の色や太文字などで表示したい場合は、RichTextクラスを使うことをおすすめします。

RichTextはtextパラメータのタイプstringではなく、InlineSpanという別のクラスになっています。

具体的な書き方としては、スタイルの異なるテキストごとに、TextSpanクラスを作成してスタイルを設定し、最後にTextSpanクラスの配列をRichTextクラスのtextパラメータに入れることで、文字のスタイルを変更できます。

 

…

Column(

                    crossAxisAlignment: CrossAxisAlignment.stretch,

                    children: [

                      const Text(“<動作ログ>”),

                      Container(

                          width: 500,

                          height: 170,

                          color: const Color.fromARGB(255, 226, 226, 226),

                          child: SingleChildScrollView(

                              child:  RichText(

                                text: TextSpan(children: [

                          TextSpan(text: "Hello World\n"),

                          TextSpan(

                              text: "HogeHogeHogeHoge\n",

                              style: TextStyle(

                                  fontSize: 35,

                                  color: Colors.red,

                                  fontWeight: FontWeight.bold)),

                          TextSpan(

                              text: "HogeHogeHogeHoge\n",

                              style:

                                  TextStyle(fontSize: 35, color: Colors.green)),

                          TextSpan(

                              text: "HogeHogeHogeHoge\n",

                              style: TextStyle(

                                  fontSize: 35, color: Colors.yellow)),

                        ]))

                    ],

),

…

しかし、RichTextクラスでは文字の選択ができなくなります…

RichTextクラス公式ドキュメントによると、選択できるようにしたい場合は、SelectionAreaやSelectableRegionクラスを合わせて使う必要があると書いてありますが、もっと簡単な方法があります!

実はSelectableTextクラスには中身をRichTextとして出力するメソッドSelectableText.rich()がありますので、そちらを使うことで簡単にRichTextかつ文字選択ができるようになります!

 

…

Column(

                    crossAxisAlignment: CrossAxisAlignment.stretch,

                    children: [

                      const Text(“<動作ログ>”),

                      Container(

                          width: 500,

                          height: 170,

                          color: const Color.fromARGB(255, 226, 226, 226),

                          child: SingleChildScrollView(

                              child:  SelectableText.rich(

                                TextSpan(children: [

                          TextSpan(text: "Hello World\n"),

                          TextSpan(

                              text: "HogeHogeHogeHoge\n",

                              style: TextStyle(

                                  fontSize: 35,

                                  color: Colors.red,

                                  fontWeight: FontWeight.bold)),

                          TextSpan(

                              text: "HogeHogeHogeHoge\n",

                              style:

                                  TextStyle(fontSize: 35, color: Colors.green)),

                          TextSpan(

                              text: "HogeHogeHogeHoge\n",

                              style: TextStyle(

                                  fontSize: 35, color: Colors.yellow)),

                        ]))

                    ],

),

…

ログ出力メソッドを作る+コード整理

さて、UI表示はできましたので、次は実際に使うためのメソッド作成とコード整理について話します。

ログの種類のenumを作成します。

 

…

enum LogType {

  unknown,

  normal,

  notice,

  warning,

  error;

}

…

そして、ログの変数を宣言します。

 

List<TextSpan> logText = []; //ログのテキスト

TextSpan _logTextSpan = const TextSpan(); //ログのUI

 

UI表示部分に変数を代入します。

 

…

Column(

                    crossAxisAlignment: CrossAxisAlignment.stretch,

                    children: [

                      const Text(“<動作ログ>”),

                      Container(

                          width: 500,

                          height: 170,

                          color: const Color.fromARGB(255, 226, 226, 226),

                          child: SingleChildScrollView(

                            child: SelectableText.rich(_logTextSpan),

                          )),

                    ],

),

…

ログを出力してUIを更新するメソッドを作成します。

 

…

appendLog(String log, LogType logType) {

    switch (logType) {

      case LogType.normal:

        logText.add(TextSpan(

            text: "- $log\n", style: const TextStyle(color: Colors.black)));

        break;




      case LogType.notice:

        logText.add(TextSpan(

            text: "- $log\n",

            style: const TextStyle(

                color: Colors.black, fontWeight: FontWeight.bold)));

        break;




      case LogType.warning:

        logText.add(TextSpan(

            text: "- $log\n",

            style: const TextStyle(color: Color.fromARGB(255, 154, 138, 0))));

        break;




      case LogType.error:

        logText.add(TextSpan(

            text: "- $log\n", style: const TextStyle(color: Colors.red)));

        break;




      default:

        logText.add(TextSpan(text: "- $log\n"));

        break;

    }




// UIを更新する

    setState(() {

      _logTextSpan = TextSpan(children: List.from(logText));

    });

  }

}

…

はい!これでログテキストとログタイプを指定し、appendLog()メソッドを実行するだけで、すぐ指定されたスタイルのログを出力できるようになりました!

様々な実行やエラーログの出力をしてみましょう〜

最後に

UI更新部分ではsetStateを使っていますが、制限や更新時の描画にかかるコストなどの問題があると思います。

もっと大きめのアプリを開発する際は、BlocやProviderなどの状態管理手法で改善できると思いますが、今回は割愛させていただきます。

 

以上、FlutterでログUIを作ってみました!

ご参考になれば嬉しいです!

ココネでは一緒に働く仲間を募集中です。

ご興味のある方は、ぜひこちらのエンジニア採用サイトをご覧ください。

→ココネ株式会社エンジニアの求人一覧

Category

Tag

%d人のブロガーが「いいね」をつけました。