[Flutter/dart] CheckboxListTileをタップ時のイベントを実装したい
概要
文字列とチェックボックスを横一列に配置したい場合はCheckboxListTileが便利です。
しかし、文字列をタップしたときに、別のページへ移動するなどのイベントを実装したい場合は注意が必要です。
class MyHomePageState extends State<MyHomePage> {
List<int> list=List.generate(5, (index) => index);
List<bool> values=List.generate(5, (index) => false);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('demo'),
),
body: Container(
padding: const EdgeInsets.all(16),
child: Column(
children: list.map((e) =>
CheckboxListTile( //これ!
value: values[e],
title: Text(
"${e}",
style: TextStyle(
fontSize: 18
),
),
onChanged: (value){
values[e]=value;
setState(() {});
}
)
).toList(),
)
)
);
}
}
問題点
CheckboxListTileにはonChangedという、チェックボックス変更時の動作を規定するプロパティがあります。チェックボックスの表示を変えたりする動作はここに実装します。
しかし、先にも述べた通り、CheckboxListTileをタップしたときに(チェック値の変更とは別の)イベントを追加したい場合は注意が必要です。
そもそもCheckboxListTileにはonTapは定義されておらず、GesutureDetectorでラップしても、タップ時にはonChangedイベントが走ってしまいます。
解決策
自力で実装しましょう。
ListTileのtrailingにCheckboxを割り当てます。
ListTileの場合は全体のonTapとtrailingのontap(onChanged)は別々に認識してくれます。
class MyCheckboxListTile extends StatefulWidget{
Widget leading;
Widget title;
Function onTap;
Function(bool) onCheckChanged;
MyCheckboxListTile({this.leading, this.title, this.onTap, this.onCheckChanged});
@override
State<StatefulWidget> createState() {
return MyCheckboxListTileState();
}
}
class MyCheckboxListTileState extends State<MyCheckboxListTile>{
bool value=false;
@override
Widget build(BuildContext context) {
return ListTile(
leading: widget.leading,
title: widget.title,
trailing: Checkbox(
value: value,
onChanged: (value){
this.value=value;
widget.onCheckChanged(value);
setState(() {});
},
),
onTap: widget.onTap,
);
}
}
class MyPage extends StatelessWidget{
List<int> list=List.generate(5, (index) => index);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('demo'),
),
body: Container(
padding: const EdgeInsets.all(16),
child: Column(
children: list.map((e) =>
MyCheckboxListTile( //ここで使う!
title: Text(
"${e}",
style: TextStyle(
fontSize: 18
),
),
onTap: (){
Navigator.of(context).push(
MaterialPageRoute(
builder: (context)=>SomePage()
)
);
},
onCheckChanged: (value){},
)
).toList()
)
)
);
}
}
タイルの1つ1つがStatefulWidgetになっているので、チェック時に該当タイルだけをリビルドすれば済みます。
結論
onTapをonChangedと別で実装したい場合はListTileを使って自力で実装しましょう。
最新記事
すべて表示やりたいこと TextFieldで入力フォームを作りたい。 例えば入力内容が金額の場合、3桁区切りで頭に¥を付けた表記にしたい。 ただしユーザにこれらを入力させるのではなく、ユーザはあくまで数字を入力するだけで、アプリ側で自動でフォーマットしたい。 方法...
現象 やってること iosシミュレータで画像をデバイスのローカルに保存 保存したパスをデータベースに保存 アプリ立ち上げ時にデータベースから画像パスを取得し、そのパスの画像を画面上に表示 起きている現象 iosシミュレータを再起動した場合、上記3で「ファイルパスが見つからな...
やりたいこと 初期値さえ決まればあとは不変な変数がある ただし、コンストラクタ起動時にはまだ決定できない このような変数について late finalで変数を定義 (何らかのタイミングで)初期化されたかどうかをチェックし、されていなければ値を入れる(チェックしないとfina...
Comments