🐷
チェックボックスで状態管理を学ぶ
ボタンのグレーアウトのロジックを作ってみた
退会機能で使うボタンを作ろうとして、ダイアログを出す以外に、CheckBoxを使用して、グレーアウトのロジックを作って、ボタンをうっかり押して、退会してしまうのを防止する方法を考えてみた。
Riverpod2.0のStateNotifierとNotifierを使用して、コードの比較をしてみました。
StateNotifierを使用した状態管理
こちらは、Riverpod2.0では、非推奨になったStateNotifierで作ったロジックです。コンストラクターに初期値を入れて使います。
checkbox_state.dart
import 'package:riverpod/riverpod.dart';
class CheckboxNotifier extends StateNotifier<bool> {
// コンストラクターに初期値を入れる.
CheckboxNotifier() : super(false);
// 状態を持ったメソッドを定義する。等しくなければチェックボックスがONになる.
// 等しければ、チェックボックスがOFFになる。最初は、OFFの状態.
void toggle() {
state = !state;
}
}
こちらが、アプリを実行するコード。チェックボックスを押すと、ボタンのグレーアウトの状態が切り替わります。
main.dart
import 'package:button_gray_out/checkbox_state.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Checkbox Example')),
body: Center(child: MyCheckboxWidget()),
),
);
}
}
// プロバイダーで読み込む
final checkboxProvider = StateNotifierProvider<CheckboxNotifier, bool>((ref) {
return CheckboxNotifier();
});
class MyCheckboxWidget extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final isChecked = ref.watch(checkboxProvider);
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Checkbox(
// if文で切り替わっているかチェックする.
// onChangedのところでメソッドを実行する.
value: isChecked,
onChanged: (bool? newValue) {
if (newValue != null) {
ref.read(checkboxProvider.notifier).toggle();
}
},
),
ElevatedButton(
// 三項演算子で、ボタンのグレーアウトの切り替えをする
onPressed: isChecked
? () {
// Perform action when the button is pressed
print('ElevatedButton pressed');
}
: null,
child: Text('Press me'),
style: ElevatedButton.styleFrom(
backgroundColor: isChecked ? Colors.redAccent : Colors.grey,
),
),
],
);
}
}
Notifierを使用した状態管理
checkbox_controller.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
class CheckBoxController extends Notifier<bool> {
// Notifierはbuildのreturnの中に、初期値を書く.
// OFFにするので初期値は、false.
build() {
return false;
}
// 状態を持ったメソッドを定義する。等しくなければチェックボックスがONになる.
// 等しければ、チェックボックスがOFFになる。最初は、OFFの状態.
void toggle() {
state = !state;
}
}
main.dartのコードはわずかしか、変更点がないですね。個人の感想ですが、今までの書き方より、新しい書き方の方がシンプルに書ける気がします。
main.dart
import 'package:button_gray_out/checkbox_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Checkbox Controller')),
body: Center(child: MyCheckboxWidget()),
),
);
}
}
// プロバイダーで読み込む
final checkBoxProvider = NotifierProvider<CheckBoxController, bool>(CheckBoxController.new);
class MyCheckboxWidget extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final isChecked = ref.watch(checkBoxProvider);
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Checkbox(
value: isChecked,
onChanged: (bool? newValue) {
// if文で切り替わっているかチェックする.
// onChangedのところでメソッドを実行する.
if (newValue != null) {
ref.read(checkBoxProvider.notifier).toggle();
}
},
),
ElevatedButton(
// 三項演算子で、ボタンのグレーアウトの切り替えをする
onPressed: isChecked
? () {
// Perform action when the button is pressed
print('Notifier toggle!');
}
: null,
child: Text('Tap'),
style: ElevatedButton.styleFrom(
backgroundColor: isChecked ? Colors.redAccent : Colors.grey,
),
),
],
);
}
}
実行結果
まとめ
こちらに完成品のソースコードを公開しています。参考にしたい方は見てみてください。
全体のソースコード
Discussion