🔍

【Flutter】選択したテキストを「Googleで検索」する

2023/10/01に公開

やること

  • テキストを選択し、コンテキストメニュー(あるいは右クリックメニュー)から、「Googleで検索」を押し、ブラウザ上で選択ワードのGoogle検索結果の画面を表示する

コード

class MyHomePage extends StatefulWidget {

  const MyHomePage({
    Key? key,
  }) : super(key: key);

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String? selectedText;

  
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Selection Area'),
        ),
        body: Center(
          child: SelectionArea(
            onSelectionChanged: (final value) {
              print(value?.plainText);
              setState(() {
                selectedText = value?.plainText;
              });
            },
            contextMenuBuilder: (context, selectableRegionState) {
              final search = ContextMenuButtonItem(
                  label: 'Googleで "$selectedText" を検索',
                  onPressed: () async {
                    if (selectedText == null) return;
                    final uri = Uri.https(
                        'www.google.co.jp', 'search', {'q': selectedText});
                    if (!await launchUrl(uri)) {
                      throw Exception('Could not launch $uri');
                    }
                  });
              return AdaptiveTextSelectionToolbar.buttonItems(buttonItems: [
                search,
                ...selectableRegionState.contextMenuButtonItems
              ], anchors: selectableRegionState.contextMenuAnchors);
            },
            child: const Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'Chat GPT',
                ),
                Text(
                  'Google Bard',
                ),
                Text(
                  'Bing Chat',
                ),
              ],
            ),
          ),
        ));
  }
}

SelectionArea

ドキュメント
childに含まれる文字列を選択可能にします。

onSelectionChanged

選択されたテキストを返します。なかったらnullが返ります。今回は逐次SetStateで保存しています。

contextMenuBuilder

名前のまま、メニューをビルドします。CopySelectAllはデフォルトで備わっている機能です。今回はそこにsearchボタンを追加しているという作りです。押されたらselectedTextを使ってuriを組んでUrl Launcherでブラウザに渡しています。
AdaptiveTextSelectionToolbarの部分はやり方が複数あるようですが、イマイチよくわからなかったので😅 とりあえず無難な形でやってみました。

ちなみに手持ちのiPadだとこんな感じで見切れてしまいました。

RichTextの場合

例えば、以下の書き方だと"Chat GPT"は選択できません。

	    Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                RichText(
                    text: const TextSpan(children: [
                  TextSpan(
                      text: 'Chat ', style: TextStyle(color: Colors.black)),
                  TextSpan(text: 'GPT', style: TextStyle(color: Colors.red)),
                ])),
                const Text(
                  'Google Bard',
                ),
                const Text(
                  'Bing Chat',
                ),
              ],
            ),

SelectableText.richを使うと、選択はできますがSelectionAreaには含まれません。

	    Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                SelectableText.rich(
                  const TextSpan(children: [
                  TextSpan(
                      text: 'Chat ', style: TextStyle(color: Colors.black)),
                  TextSpan(text: 'GPT', style: TextStyle(color: Colors.red)),
                ])),
                const Text(
                  'Google Bard',
                ),
                const Text(
                  'Bing Chat',
                ),
              ],
            ),

Text.richを使うことで、SelectionAreaとして選択できます。

	    Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text.rich(
                  const TextSpan(children: [
                  TextSpan(
                      text: 'Chat ', style: TextStyle(color: Colors.black)),
                  TextSpan(text: 'GPT', style: TextStyle(color: Colors.red)),
                ])),
                const Text(
                  'Google Bard',
                ),
                const Text(
                  'Bing Chat',
                ),
              ],
            ),

動機

5chやふたばchに対応した掲示板ビューアを開発中なんですが(記事はこちら)「選択テキストを検索」は自分でもよく使う機能ということもあり実装しようと思いました。アプリバージョン1.1.30以降で対応しています。

まとめ

選択テキストの処理は様々なアプリでよくあるはずなので、今後もうまく使っていきたいところです。
まだ試してないんですが、入力フォームでもコンテキストメニューを拡張できるようなので、入力されたテキストを処理する用途でも使えそうです。
お読みいただきありがとうございました。

Discussion