対象者
- Flutterを使用している中級開発者
- キーボードの表示・非表示の切り換えを検知する方法を知りたい方
はじめに
モバイルアプリケーションの開発において、ユーザーがテキスト入力を行う際にキーボードの表示・非表示を検知することは、UIの最適化やアプリの挙動を改善するために非常に重要です。今回は、Flutterを使用してキーボードの状態を捕捉する方法について説明します。
キーボードの有無で画面レイアウトを変えようと、TextFieldへのフォーカス有無で判断しようとしましたが、フォーカスが合っても、キーボードがない状態があったので、今回の方法でやり直し
キーボードの捕捉方法
WidgetsBindingObserver の設定
WidgetsBindingObserver
は、Flutterのウィジェットライフサイクルやその他の重要なイベントを監視するためのオブザーバーです。キーボードの表示・非表示の状態を検知するのにも使えます。
以下のコードスニペットでは、MyHomePage
ステートフルウィジェットの中で WidgetsBindingObserver
を設定し、キーボードの状態を検知する方法を示しています。
キーボードの表示・非表示の状態が切り替わると、didChangeMetrics()
が実行されます。
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeMetrics() {
}
}
キーボード有無の判定
didChangeMetrics
メソッド内で、MediaQuery.of(context).viewInsets.vertical
を使用してキーボードの表示状態を検知します。viewInsets.vertical
が0より大きい場合、キーボードが表示されていると判断し、その結果を _isKeyboardVisible
変数に格納します。この変数の変更を監視し、UIを更新します。
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
var _isKeyboardVisible = false;
@override
void didChangeMetrics() {
final newValue = 0 < MediaQuery.of(context).viewInsets.vertical;
if (newValue != _isKeyboardVisible) {
setState(() {
_isKeyboardVisible = newValue;
});
}
}
}
このコードにより、キーボードの表示・非表示の状態をリアルタイムで検知し、UIに反映させることができます。
Q&A
Q1: Flutterでキーボードの表示・非表示を検知する方法は何ですか?
A1: Flutterでは、WidgetsBindingObserver
を使用してキーボードの表示・非表示を検知できます。具体的には、didChangeMetrics
メソッド内でMediaQuery.of(context).viewInsets.vertical
をチェックし、0より大きい場合はキーボードが表示されていると判断します。これにより、リアルタイムでキーボードの状態をUIに反映させることが可能です。
Q2: MediaQuery.of(context).viewInsets.vertical
が0になります
おそらくWidget Tree(多分正確には Element Tree)上にMediaQuery
が複数あり、キーボードのサイズと紐付いていないMediaQuery
を取得していると思われます。私の場合、以下でScaffold
を経由すると、取得できました。お試しください。
0 < MediaQuery.of(Scaffold.of(context).context).viewInsets.bottom
Q3: didChangeMetricsは本来何をするメソッドですか?
A3: didChangeMetricsは、FlutterのWidgetsBindingObserverインターフェースの一部で、アプリケーションのウィジェットのサイズや位置に関する変更を検知するために呼び出されるメソッドです。このメソッドは、キーボードの表示・非表示、デバイスの回転、画面サイズの変更など、ビューに影響を与えるメトリクスの変化が発生した際にトリガーされます。これにより、動的にUIを更新するためのフックを提供します。
まとめ
Flutterでキーボードの表示・非表示を検知する方法について説明しました。WidgetsBindingObserver
を使用することで、キーボードの状態を簡単に検知でき、ユーザーエクスペリエンスを向上させることができます。ぜひ、アプリケーションの開発に役立ててください。
参考
- Flutter Keyboard listen on hide and show
- Keyboard not being detected. MediaQuery.of(context).viewInsets.bottom always returns 0.0
ソース(main.dartにコピペして動作確認用)
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
var _isKeyboardVisible = false;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeMetrics() {
final newValue = 0 < MediaQuery.of(context).viewInsets.vertical;
if (newValue != _isKeyboardVisible) {
setState(() {
_isKeyboardVisible = newValue;
});
}
// 0 < MediaQuery.of(Scaffold.of(context).context).viewInsets.bottom
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text('Keyboard is visible: $_isKeyboardVisible'),
TextField(),
TextField(),
],
),
),
),
);
}
}