🔍
【Flutter】選択したテキストを「Googleで検索」する
やること
- テキストを選択し、コンテキストメニュー(あるいは右クリックメニュー)から、「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
名前のまま、メニューをビルドします。Copy
やSelectAll
はデフォルトで備わっている機能です。今回はそこに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