【Flutter】テキストの一部をハイライト表示する3つの方法

2 min read読了の目安(約2400字

スクリーン1

アプリ内で検索結果をキーワードでハイライト表示したいなと思い色々調べたのでメモします。

方法1 RichTextを使う

RichTextウィジェットを使う方法です。
TextSpanウィジェットは入れ子構造なので途中でスタイルを変えることができます。

main.dart
class HomePage extends StatelessWidget {
  final highlightStyle = TextStyle(
    color: Colors.red,
    backgroundColor: Colors.yellow,
    fontWeight: FontWeight.bold,
  );

  
  Widget build(BuildContext context) {
    return RichText(
      text: TextSpan(
        children: [
          TextSpan(text: "隣の"),
          TextSpan(text: "客", style: highlightStyle),
          TextSpan(text: "はよく柿食う"),
          TextSpan(text: "客", style: highlightStyle),
          TextSpan(text: "だ。"),
        ],
      ),
    );
  }
}

方法2 Text.rich()を使う

Textウィジェットのrich()コンストラクタを使う方法です。
方法1とほぼ同じような記述になります。

main.dart
class HomePage extends StatelessWidget {
  final highlightStyle = TextStyle(
    color: Colors.red,
    backgroundColor: Colors.yellow,
    fontWeight: FontWeight.bold,
  );

  
  Widget build(BuildContext context) {
    return Text.rich(
      TextSpan(
        children: [
          TextSpan(text: "隣の"),
          TextSpan(text: "客", style: highlightStyle),
          TextSpan(text: "はよく柿食う"),
          TextSpan(text: "客", style: highlightStyle),
          TextSpan(text: "だ。"),
        ],
      ),
    );
  }
}

方法3 動的にハイライト表示する

元の文字列をキーワードの位置で分解して、TextSpanウィジェットで一部ステイルを変更して…という感じで関数を自作できそうですが、既に素晴らしいパッケージがあるのでそちらを使用します。

https://pub.dev/packages/substring_highlight

インストール:

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  substring_highlight: ^0.1.2

サンプルコード:

main.dart
import 'package:flutter/material.dart';
import 'package:substring_highlight/substring_highlight.dart';

class HomePage extends StatelessWidget {
  final defaultStyle = TextStyle(
    color: Colors.white,
    fontSize: 18.0,
  );
  final highlightStyle = TextStyle(
    color: Colors.greenAccent[200],
    fontWeight: FontWeight.bold,
    fontSize: 24.0,
  );

  
  Widget build(BuildContext context) {
    return SubstringHighlight(
      // 元となる文字列
      text: "かえるぴょこぴょこみぴょこぴょこ。\nあわせてぴょこぴょこむぴょこぴょこ。",

      // 検索キーワード
      term: "ぴょこ",

      // デフォルトのスタイル
      textStyle: defaultStyle,

      // ハイライト時のスタイル
      textStyleHighlight: highlightStyle,
    );
  }
}

実行結果:

スクリーン2

以上です。