🎩

ボタンのグレーアウトのロジックを考えてみた!

2022/08/30に公開

友達に頼まれて作ってみた!

TextFieldに値が入力されないと、ボタンがグレーアウトして押せないロジックをriverpodで考えるようにいわれて、やってみたのですが、結構難しかったですね😅

海外の記事を参考になんとか頑張って作りました!

完成品のサンプルコード
https://github.com/sakurakotubaki/button-gray-out

今回参考にしたコードはこちらです。

// 参考にしたコード
class _TempDialogState extends State<TempDialog> {
  final TextEditingController _inputController = TextEditingController();
  final TextEditingController _inputController2 = TextEditingController();
  bool enable = false;

  
  void initState() {
    super.initState();
  }

  
  void dispose() {
    _inputController.dispose();
    _inputController2.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Center(
            child: Column(children: [
              TextField(
                controller: _inputController,
                onChanged: (data) {
                  if (_inputController.text.isEmpty ||
                      _inputController2.text.isEmpty) {
                    enable = false;
                  } else {
                    enable = true;
                  }
                  setState(() {});
                },
              ),
              TextField(
                controller: _inputController2,
                onChanged: (data) {
                  if (_inputController.text.isEmpty ||
                      _inputController2.text.isEmpty) {
                    enable = false;
                  } else {
                    enable = true;
                  }
                  setState(() {});
                },
              ),
              ElevatedButton(
                onPressed: enable ? () {} : null,
                child: Text('${enable}'),
              )
            ])),
      ),
    );
  }
}

riverpodを使用して、作ってみたコードです。今回のポイントは、onChange()で、取得した値を判定するようです。
コードが少ないから、フォルダ分けなくてもいいと思ったのですが、分離させたかったので、やってみました。

privider/provider.dart
// TextEditingControllerを使うためのProvider
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

// StateProvider は外部から変更が可能なステート(状態)を公開するプロバイダです。
// TextEditingControllerを使うためのProvider
final textProvider = StateProvider.autoDispose((ref) {
  // riverpodで使うには、('')が必要
  return TextEditingController(text: '');
});
// bool型を使うためのProvider。初期値はfalseにする
final enableProvider = StateProvider.autoDispose((ref) => false);
main.dart
import 'package:button_glay_out/provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(
    const ProviderScope(child: MyApp()),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return MaterialApp(home: Home());
  }
}

class Home extends ConsumerWidget {
  
  Widget build(BuildContext context, WidgetRef ref) {
    // コードの書き方が変わったのか、[(.state).state]と外と中に.stateを
    // 書かないといけない!
    // 2回目の.stateは、使う時に呼び出して使う。
    // controllerProviderは大丈夫みたい?
    final controllerProvider = ref.watch(textProvider.state);
    // bool型のProviderを呼び出す!
    final boolProvider = ref.watch(enableProvider.state);

    return Scaffold(
      appBar: AppBar(title: const Text('ButtonGrayOut')),
      body: Center(
        child: Column(
          children: [
            TextField(
              // ここで、finalに格納した、Providerを使う!
              controller: controllerProvider.state,
              // onChangedを使わないと、if文の判定ができない!
              onChanged: (data) {
                if (controllerProvider.state.text.isNotEmpty) {
                  boolProvider.state = false;
                } else {
                  boolProvider.state = true;
                }
              },
              decoration: const InputDecoration(
                border: OutlineInputBorder(),
                hintText: 'テキストを入力してください!',
              ),
            ),
            const SizedBox(height: 20),
            // 三項演算子でボタンをtrueなら、グレーアウト
            // falseなら、ボタンを押せるようにする。
            // 文字が入力されれば、ボタンは押せるようになる!
            ElevatedButton(
              onPressed: boolProvider.state
                  ? null
                  : () {
		  // 取得した値をデバッグする
                      print(controllerProvider.state.text);
                    },
              child: Text('送信'),
            ),
          ],
        ),
      ),
    );
  }
}

最後に

ビジネスロジックを考えて作ってみたのですが、成功したのは、今回が初めてかもしれないですね😅
いい勉強になりました。

Discussion