Home > front end >  how to disable button in Flutter 3.3.4
how to disable button in Flutter 3.3.4

Time:10-20

in Flutter 3.3.4 , I want control the state of the button by passing an object with its properties . I tried some solutions in stackoverflow (e.g How do I disable a Button in Flutter? ),but failed。

I print the flag of the object , it looks right.

here is my code

// Copyright 2018 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    SwitchWidget wifiSwitch = SwitchWidget();
    // SwitchWidget timeSwitch = SwitchWidget();
    // SwitchWidget locationSwitch = SwitchWidget();

    return MaterialApp(
      title: 'Startup N1ame Generator',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Startup Name Generator'),
        ),
        body: Center(
          child: Row(
            children: [
              Column(children: [wifiSwitch]),
              Column(children: [ButtonWidget(wifiSwitch)])
            ],
          ),
        ),
      ),
    );
  }
}

class SwitchWidget extends StatefulWidget {
  bool flag = true;

  SwitchWidget({Key? key}) : super(key: key);

  @override
  State<SwitchWidget> createState() => _SwitchWidgetState(this);
}

class _SwitchWidgetState extends State<SwitchWidget> {
  SwitchWidget switchWidget;

  _SwitchWidgetState(this.switchWidget);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Switch(
        value: switchWidget.flag,
        onChanged: (newValue) => {
          setState(() {
            switchWidget.flag = newValue;
            print("-----------${switchWidget.flag}");
          })
        },
      ),
    );
  }
}

class ButtonWidget extends StatefulWidget {
  late SwitchWidget _switchWidget;

  SwitchWidget get switchWidget => _switchWidget;

  set switchWidget(SwitchWidget switchWidget) => {
        print('The ButtonWidget is $switchWidget.'),
        _switchWidget = switchWidget
      };

  ButtonWidget(switchWidget, {Key? key}) : super(key: key) {
    this.switchWidget = switchWidget;
  }

  @override
  State<ButtonWidget> createState() => _ButtonWidgetState(switchWidget);
}

class _ButtonWidgetState extends State<ButtonWidget> {
  SwitchWidget switchWidget;

  _ButtonWidgetState(this.switchWidget);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.fromLTRB(50, 1, 1, 1),
      child: ElevatedButton(
          // color: Colors.blue,
          // disabledColor: Colors.grey,
          // textColor: Colors.black,
          child: Text("123"),
          // onPressed: () {},
          onPressed: this.switchWidget.flag ? _incrementCounter : null,
          style: ButtonStyle(
            foregroundColor: MaterialStateProperty.resolveWith(
              (states) {
                if (states.contains(MaterialState.disabled)) {
                  return Colors.grey;
                } else {
                  return Colors.white;
                }
              },
            ),
          )),
    );
    {}
  }

  void _incrementCounter() {
    print("object******** ${this.switchWidget.flag}");

  }
}

CodePudding user response:

Why do you pass a reference of SwitchWidget to _SwitchWidgetState? You should move the property bool flag = true; to _SwitchWidgetState and then change it directly in setState(() => flag = newValue);.

Also, your ButtonWidget is not rebuilt on change in SwitchWidget. You'll have to use some sort of state management in order to disable the button on a state change of your switch widget.

For example using callbacks:

import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_svg/flutter_svg.dart';

class ParentWidget extends StatefulWidget {
  const ParentWidget({super.key});

  @override
  State<ParentWidget> createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  bool _isDisabled = false;
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SwitchWidget(initialValue: true, onChanged: (val) => setState(() => _isDisabled = val)),
        ButtonWidget(isDisabled: _isDisabled),
      ],
    );
  }
}

class SwitchWidget extends StatefulWidget {
  final bool initialValue;
  final void Function(bool) onChanged;
  const SwitchWidget({super.key, required this.onChanged, required this.initialValue});

  @override
  State<SwitchWidget> createState() => _SwitchWidgetState();
}

class _SwitchWidgetState extends State<SwitchWidget> {
  late bool _value;

  @override
  void initState() {
    super.initState();
    _value = widget.initialValue;
  }

  @override
  Widget build(BuildContext context) {
    return Switch(
      value: _value,
      onChanged: (val) {
        setState(() => _value = val);
        widget.onChanged(val);
      },
    );
  }
}

class ButtonWidget extends StatelessWidget {
  final bool isDisabled;
  const ButtonWidget({super.key, required this.isDisabled});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: isDisabled
          ? null
          : () {
              //Some logic
            },
      child: Text("Press me!"),
    );
  }
}

CodePudding user response:

You can pass null where you place your function, or even some of Flutter's Widgets already have the enabled property. But setState and change the function to null and you should get what you want.

  • Related