如何在Flutter中禁用按钮?


114

我刚刚开始了解Flutter,但是我在弄清楚如何设置按钮的启用状态时遇到了麻烦。

在文档中,它说设置onPressed为null以禁用按钮,并为它提供一个值以启用它。如果按钮在生命周期中继续处于相同状态,那就很好。

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

所以我的问题是我该怎么做?这似乎是一个非常简单的要求,但是我在文档中找不到有关如何执行操作的任何内容。

谢谢。


您能说明一下“如果按钮在生命周期中继续保持相同状态就可以了”的意思。?
塞思·拉德

Answers:


126

我认为您可能要向按钮中引入一些帮助器功能build以及有状态的小部件以及一些要注销的属性。

  • 使用StatefulWidget / State并创建一个变量来保存您的条件(例如isButtonDisabled
  • 最初将其设置为true(如果您要这样做)
  • 呈现按钮时,请勿将onPressed直接设置为null某个或某些函数onPressed: () {}
  • 而是使用三元或辅助函数有条件地设置它(以下示例)
  • isButtonDisabled作为此条件的一部分进行检查,并返回一个null或某些函数。
  • 当按下按钮时(或每当您要禁用按钮时),使用setState(() => isButtonDisabled = true)来翻转条件变量。
  • Flutter将build()使用新状态再次调用该方法,并且按钮将通过null按下处理程序进行渲染并被禁用。

这是使用Flutter计数器项目的更多背景信息。

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,
    );
  }
}

在此示例中,我使用内联三元有条件地设置Textand 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();
      };
    }
  }

3
您需要添加粗箭头功能作为参数,否则启用按钮后将立即调用_i​​ncrementCounter()函数。这样,它实际上将一直等到单击按钮为止:onPressed应该看起来像这样:onPressed: _isButtonDisabled ? null : () => _incrementCounter
Vit Veres

2
@vitVeres通常是正确的,但是_counterButtonPress()返回一个函数,return () {}因此这是故意的。我不想在这里使用粗箭头,因为我希望函数执行并返回null并禁用按钮。
Ashton Thomas

@AshtonThomas是的,在提取的方法_counterButtonPress()中,它与您所解释的完全相同,但是在建议提取之前,我使用三元运算符引用了该代码。在第一个示例中,当应启用按钮时,它将导致_incrementCounter()方法的执行。下次,我将尝试指出我的意思是:)
Vit Veres

30
disabledFlutter团队使用物业有什么问题?这只是不直观:-/
卷曲

1
正确的方法是使用AbsorbPointer或IgnorePointer。通过将onPressed设置为null,可以简单地使用小部件方式而不是逻辑方式。
ejdrian313

93

根据文档:

“如果onPressed回调为null,则该按钮将被禁用,并且默认情况下将类似于DisabledColor中的平面按钮。”

https://docs.flutter.io/flutter/material/RaisedButton-class.html

因此,您可以执行以下操作:

    RaisedButton(
      onPressed: calculateWhetherDisabledReturnsBool() ? null : () => whatToDoOnPressed,
      child: Text('Button text')
    );

2
从文档来看,这就是实现的方式。有了这样接受的答案性能disabledElevationdisabledColor并且DisabledTextColor将无法工作按预期。
乔尔·布罗斯特罗姆(JoelBroström),

Pff感谢Steve这个人,他不打算遍历当前接受的答案的所有代码。@ chris84948,请考虑将其更改为接受的答案。
CularBytes


17

设置

onPressed: null // disables click

onPressed: () => yourFunction() // enables click

1
在此解决方案中,的值onPressed始终是一个函数,因此即使isEnabled设置了该属性,按钮也会忽略click事件,因此该按钮呈现为“ clickable” 。要真正禁用该按钮,请使用RaisedButton(onPressed: isEnabled ? _handleClick : null
Curly

15

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

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

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


9

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

例如,按钮,开关,复选框等。

只需onPressed如下所示设置属性

onPressed : null返回禁用的小部件

onPressed : (){}onPressed : _functionName返回Enabled小部件


6

您还可以使用AbsorbPointer,并且可以通过以下方式使用它:

AbsorbPointer(
      absorbing: true, // by default is true
      child: RaisedButton(
        onPressed: (){
          print('pending to implement onPressed function');
        },
        child: Text("Button Click!!!"),
      ),
    ),

如果您想进一步了解此小部件,可以查看以下链接Flutter Docs


2
Ignore- / AbsorbPointer不将禁用样式视为提醒:-)
Pascal

4

我认为这是最简单的方法:

RaisedButton(
  child: Text("PRESS BUTTON"),
  onPressed: booleanCondition
    ? () => myTapCallback()
    : null
)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.