⌨️

FocusScope class Flutterでkeyboardを閉じる

2024/02/26に公開

📕Overview

https://api.flutter.dev/flutter/widgets/FocusScope-class.html

FocusScope は Focus と似ていますが、その子孫のスコープとしても機能し、 フォーカスのトラバーサルをスコープされたコントロールに制限します。

たとえば、ルートがプッシュされると新しい FocusScope が自動的に作成され、フォーカスのトラバーサルが前のルートのコントロールに移動しないようにします。

ウィジェットをグループ化し、特定の順序でトラバースされるようにしたいが、フォーカスがグループから離れる可能性がある場合は、FocusTraversalGroup を使用します。

Focus と同様に、FocusScope にも onFocusChange があり、このウィジェットにフォーカスが移ったときや、このウィジェットからフォーカスが外れたときに通知されます。

onKey 引数では、このノードまたはその子ノードのいずれかがフォーカスを持ったときに呼び出されるキー・イベント・ハンドラを指定できます。キーは、最初にフォーカスが当たった主ウィジェットに渡され、その後、そのノードの祖先を通して伝搬し、そのうちの 1 つが onKey から KeyEventResult.handled を返し、イベントを処理したことを示すと停止します。

FocusScopeNode を管理することは、そのライフサイクルを管理し、フォーカスの変化をリッスンし、必要に応じて再ペアレントして、フォーカス階層とウィジェット階層を同期させることを意味します。このウィジェットは、これらすべてを行います。FocusScope ウィジェットを使用せず、ノード管理を自分で行う必要がある場合の詳細については、FocusScopeNode を参照してください。

FocusScopeNode は、その子孫の中で最後にフォーカスされた FocusNode を記憶しており、そのフォーカスを次/前のノードや特定の

🧷summary

使うことが想定されるusecaseは、ボタンを押したときに、keyboardを閉じるロジックを実装したいときでした。皆ためかっこよくないですが、このようなUIを作って試してみました。

❌ボタンを押すか、コメントするボタンを押すと、FocusScope.of(context).unfocus();が実行され、keyboardが閉じます。標準機能で閉じれると思ったのですが、改行できるTextFieldにすると、使えませんでした!

サンプルコード:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

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

class _MyHomePageState extends State<MyHomePage> {
  final List<String> items = [
    'aaaa',
    'aaaa',
    'aaaa',
  ];
  TextEditingController _textEditingController = TextEditingController();

  
  void dispose() {
    _textEditingController.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('Cook Book'),
      ),
      body: Stack(
        children: [
          Container(
              color: Colors.green,
              child: ListView.builder(
                itemCount: items.length,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                    title: Text(items[index]),
                  );
                },
              )),
          Align(
            alignment: Alignment.bottomCenter,
            child: Container(
              color: Colors.white,
              height: 100,
              child: Row(
                children: [
                  const SizedBox(width: 30),
                  SizedBox(
                      width: 150,
                      child: TextField(
                        controller: _textEditingController,
                        decoration: InputDecoration(
                          suffixIcon: IconButton(
                            onPressed: () => FocusScope.of(context).unfocus(),
                            icon: const Icon(Icons.clear, color: Colors.grey, size: 15),
                          ),
                          border: OutlineInputBorder(),
                        ),
                        maxLines: null,
                      )),
                  const SizedBox(
                    width: 15,
                  ),
                  ElevatedButton(
                    child: const Text("コメントする"),
                    onPressed: () {
                      setState(() {
                        items.add(_textEditingController.text);
                      });
                      FocusScope.of(context).unfocus();
                      _textEditingController.clear();
                    },
                  ),
                ],
              ),
            ),
          )
        ],
      ),
    );
  }
}

🧑‍🎓thoughts

今回は、keyboardを閉じる方法を調べていたときに、メモ書きですが記事を書くことにしました。Swiftとかだと設定しないと閉じれなかったような。SwiftUIは問題なかったかな🤔
必要な場面があると思うので、参考になりそうでしたが使ってみてください。

Discussion