FlutterのTextFieldを複数並べたときに、キーボード上の「次へ・確定」ボタンを押下するだけで
次のTextFieldや画面遷移をさせる方法を紹介します。
実装イメージ
以下の操作手順をしたものをMovieにて表示します。
- 初期画面にてListを描画したものが表示
- 右下の「+」ボタンをタップするとListを追加する画面に遷移
- TextAをタップしてキーボードから文字を入力し、右下の「next」をタップ
- TextBにフォーカスが変わる。再び文字を入力して、右下の「done」をタップ
- 画面が一つ戻り、ListにTextAとTextBに入力した文字が追加されてListが表示
実装ソース
以下のようなWidgetを作成することで実装できます。
ソース自体は少し長いですが、下記に関するソースに関連する部分は赤と青でハイライトしています。
(下の方にいます!!笑)
- nextをタップして、次のTextFieldに遷移
- doneをタップして、前画面に遷移
前者は
TextFieldのフィールドの一つであるtextInputActionを定義してあげることで、
例えばColumnの次に定義されているTextFieldにフォーカスさせることができます。
後者は、
TextFieldのフィールドの一つであるonSubmittedを定義してあげることで、
doneをタップした後の動作を指定してあげています。
(今回ならばNavigator.of(context).pop([_text1, _text2])というように
画面のテキスト部分に入力された値を保持して前Widgetに渡しています。)
class TodoListPage extends StatefulWidget {
const TodoListPage({super.key});
@override
State<TodoListPage> createState() => _TodoListPageState();
}
List<String> weekly_todo = <String>[
'one',
'two',
'three',
'four',
'five',
];
class _TodoListPageState extends State<TodoListPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemBuilder: ((BuildContext context, int index) {
return Container(
height: 60,
child: Card(
child: ListTile(
title: Text(weekly_todo[index]),
leading: Icon(
IconData(0xef53, fontFamily: 'MaterialIcons'),
size: 40.0,
),
),
),
);
}),
itemCount: weekly_todo.length,
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final List newTodoText = await Navigator.of(context).push(
MaterialPageRoute(
builder: ((context) {
return TodoAddPage();
}),
),
);
if (newTodoText != null) {
setState(() {
// リスト追加
weekly_todo.add(newTodoText[0]);
weekly_todo.add(newTodoText[1]);
});
}
},
child: Icon(Icons.add),
),
);
}
}
class TodoAddPage extends StatefulWidget {
const TodoAddPage({
Key? key,
}) : super(key: key);
@override
State<TodoAddPage> createState() => _TodoAddPageState();
}
class _TodoAddPageState extends State<TodoAddPage> {
String _text1 = '';
String _text2 = '';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
TextField(
onChanged: ((String value) {
setState(() {
_text1 = value;
});
}),
decoration: InputDecoration(hintText: 'TextA'),
textInputAction: TextInputAction.next,
),
TextField(
onChanged: ((String value) {
setState(() {
_text2 = value;
});
}),
onSubmitted: (v) {
Navigator.of(context).pop([_text1, _text2]);
},
decoration: InputDecoration(hintText: 'TextB'),
),
],
),
),
);
}
}
コメント