我刚开始掌握Flutter的窍门,但我不知道如何设置按钮的启用状态。

从文档中,它说将onPressed设置为null来禁用按钮,并给它一个值来启用它。如果按钮在生命周期中继续处于相同的状态,这是没问题的。

我得到的印象是,我需要创建一个自定义的有状态小部件,它将允许我以某种方式更新按钮的启用状态(或onPressed回调)。

我的问题是我该怎么做?这似乎是一个非常简单的要求,但我在文档中找不到任何关于如何做到这一点的东西。

谢谢。


当前回答

如果你正在寻找一种快速的方法,而不关心让用户在一个按钮上点击多次。你也可以这样做:

// Constant whether button is clicked
bool isClicked = false;

然后在onPressed()函数中检查用户是否已经单击了按钮。

onPressed: () async {
    if (!isClicked) {
       isClicked = true;
       // await Your normal function
    } else {
       Toast.show(
          "You click already on this button", context,
          duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
    }
}

其他回答

大多数小部件的启用和禁用功能是相同的。

前,按钮,开关,复选框等。

只需设置onPressed属性,如下所示

onPressed: null返回禁用小部件

onPressed:(){}或onPressed: _functionName返回启用的小部件

如果你正在寻找一种快速的方法,而不关心让用户在一个按钮上点击多次。你也可以这样做:

// Constant whether button is clicked
bool isClicked = false;

然后在onPressed()函数中检查用户是否已经单击了按钮。

onPressed: () async {
    if (!isClicked) {
       isClicked = true;
       // await Your normal function
    } else {
       Toast.show(
          "You click already on this button", context,
          duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
    }
}

有两种方法:

1- https://stackoverflow.com/a/49354576/5499531

2-你可以使用MaterialStatesController:

final _statesController = MaterialStatesController();

然后将状态更改为:

_statesController.update(
   MaterialState.disabled,
   true, // or false depending on your logic
);

在你的按钮上

ElevatedButton(
    onPressed: _onPressed,
    statesController: _statesController,
    child: Text("Awesome"),
),

此外,你可以改变按钮的风格,当禁用: 在主题设置中:

....
elevatedButtonTheme: ElevatedButtonThemeData(
              style: ElevatedButton.styleFrom(
                backgroundColor: colors.primary500, // set your own color
                textStyle: button, // set your own style
                onPrimary: colors.onPrimary100, // set your own color
                enableFeedback: true,
                disabledBackgroundColor: colors.primary300, // set your own color
                disabledForegroundColor: colors.primary300, // set your own color
                disabledMouseCursor: SystemMouseCursors.forbidden, // when is disable the change the cursor type
              ),
            ),
...

对于特定且数量有限的小部件,将它们包装在小部件IgnorePointer中正是这样做的:当它的忽略属性被设置为true时,子小部件(实际上是整个子树)是不可点击的。

IgnorePointer(
    ignoring: true, // or false
    child: RaisedButton(
        onPressed: _logInWithFacebook,
        child: Text("Facebook sign-in"),
        ),
),

否则,如果您打算禁用整个子树,请查看AbsorbPointer()。

我认为您可能需要引入一些帮助函数来构建按钮,以及一个有状态的小部件以及一些要关闭的属性。

Use a StatefulWidget/State and create a variable to hold your condition (e.g. isButtonDisabled) Set this to true initially (if that's what you desire) When rendering the button, don't directly set the onPressed value to either null or some function onPressed: () {} Instead, conditionally set it using a ternary or a helper function (example below) Check the isButtonDisabled as part of this conditional and return either null or some function. When the button is pressed (or whenever you want to disable the button) use setState(() => isButtonDisabled = true) to flip the conditional variable. Flutter will call the build() method again with the new state and the button will be rendered with a null press handler and be disabled.

这里是一些更多的上下文使用颤振计数器项目。

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  bool _isButtonDisabled;

  @override
  void initState() {
    _isButtonDisabled = false;
  }

  void _incrementCounter() {
    setState(() {
      _isButtonDisabled = true;
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("The App"),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text(
              'You have pushed the button this many times:',
            ),
            new Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
            _buildCounterButton(),
          ],
        ),
      ),
    );
  }

  Widget _buildCounterButton() {
    return new RaisedButton(
      child: new Text(
        _isButtonDisabled ? "Hold on..." : "Increment"
      ),
      onPressed: _isButtonDisabled ? null : _incrementCounter,
    );
  }
}

在这个例子中,我使用了一个内联三元来有条件地设置Text和onPressed,但它可能更适合你将其提取到一个函数中(你也可以使用相同的方法来更改按钮的文本):

Widget _buildCounterButton() {
    return new RaisedButton(
      child: new Text(
        _isButtonDisabled ? "Hold on..." : "Increment"
      ),
      onPressed: _counterButtonPress(),
    );
  }

  Function _counterButtonPress() {
    if (_isButtonDisabled) {
      return null;
    } else {
      return () {
        // do anything else you may want to here
        _incrementCounter();
      };
    }
  }