如何在Flutter中禁用按钮?

chr*_*948 59 button dart flutter

我刚刚开始了解Flutter,但我无法弄清楚如何设置按钮的启用状态.

从文档中,它表示设置onPressed为null以禁用按钮,并为其提供一个值以启用它.如果按钮在生命周期中继续处于相同状态,则此功能正常.

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

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

谢谢.

Ash*_*mas 72

我想你可能想要为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,
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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();
      };
    }
  }
Run Code Online (Sandbox Code Playgroud)

  • 您需要添加胖箭头函数作为参数,否则启用按钮后将立即调用_i​​ncrementCounter()函数。这样,它实际上将等待直到单击按钮为止:onPressed应该看起来像这样:`onPressed:_isButtonDisabled?null:()=&gt; _incrementCounter` (3认同)
  • @vitVeres 这通常是正确的,但 _counterButtonPress() 正在返回一个函数 `return () {}` 所以这是故意的。我不想在这里使用粗箭头,因为我希望函数执行并返回 `null` 并禁用按钮。 (3认同)
  • Flutter团队使用“ disabled”属性有什么问题?这只是不直观:-/ (2认同)
  • 这还不够好,因为它假设 onPress: 是同步代码,而该代码很可能是异步且可操作的,将每个按钮代码拆分为多个函数来解决这个问题会导致维护噩梦 (2认同)

Ste*_*der 46

根据文件:

"如果onPressed回调为空,则该按钮将被禁用,默认情况下将类似于disabledColor中的平面按钮."

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

所以,你可能会这样做:

    RaisedButton(
      onPressed: calculateWhetherDisabledReturnsBool() ? null : () => whatToDoOnPressed,
      child: Text('Button text')
    );
Run Code Online (Sandbox Code Playgroud)

  • 从文档来看,这就是它的实现方式。使用诸如“disabledElevation”、“disabledColor”和“DisabledTextColor”之类的公认答案属性将无法按预期工作。 (6认同)
  • 这个答案应该是公认的,该方法按照文档的预期更简单 (3认同)
  • 虽然,在 null 安全之后我们不能使用 'null' 所以你可以使用 `onPressed: _isLoading ?() =&gt; {} : () =&gt; _signImWithGoogle(上下文),` (3认同)
  • 噗,谢谢史蒂夫,他不打算遍历当前接受的答案的所有代码。@chris84948,考虑将其更改为接受的答案。 (2认同)

BIN*_*GAR 23

简单的答案是onPressed : null给出一个禁用的按钮。


Mat*_*Pag 15

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

RaisedButton(
  child: Text("PRESS BUTTON"),
  onPressed: booleanCondition
    ? () => myTapCallback()
    : null
)
Run Code Online (Sandbox Code Playgroud)


Jua*_* T. 14

你也可以使用 AbsorbPointer,你可以通过以下方式使用它:

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

如果您想了解有关此小部件的更多信息,可以查看以下链接Flutter Docs

  • Ignore-/AbsorbPointer 不会将禁用的样式视为提醒:-) (3认同)

edm*_*ond 9

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

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

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


Idu*_*ool 8

这个答案是基于更新按钮TextButton/ElevatedButtonOutlinedButtonFlutter 2.x

尽管如此,仍会根据onPressed属性启用或禁用按钮。如果该属性为空,则按钮将被禁用。如果您将功能分配给onPressed那么按钮将被启用。在下面的片段中,我展示了如何启用/禁用按钮并相应地更新它的样式。

这篇文章还说明了如何将不同的样式应用于新的 Flutter 2.x 按钮。

在此处输入图片说明

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool textBtnswitchState = true;
  bool elevatedBtnSwitchState = true;
  bool outlinedBtnState = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: <Widget>[
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                TextButton(
                  child: Text('Text Button'),
                  onPressed: textBtnswitchState ? () {} : null,
                  style: ButtonStyle(
                    foregroundColor: MaterialStateProperty.resolveWith(
                      (states) {
                        if (states.contains(MaterialState.disabled)) {
                          return Colors.grey;
                        } else {
                          return Colors.red;
                        }
                      },
                    ),
                  ),
                ),
                Column(
                  children: [
                    Text('Change State'),
                    Switch(
                      value: textBtnswitchState,
                      onChanged: (newState) {
                        setState(() {
                          textBtnswitchState = !textBtnswitchState;
                        });
                      },
                    ),
                  ],
                )
              ],
            ),
            Divider(),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                ElevatedButton(
                  child: Text('Text Button'),
                  onPressed: elevatedBtnSwitchState ? () {} : null,
                  style: ButtonStyle(
                    foregroundColor: MaterialStateProperty.resolveWith(
                      (states) {
                        if (states.contains(MaterialState.disabled)) {
                          return Colors.grey;
                        } else {
                          return Colors.white;
                        }
                      },
                    ),
                  ),
                ),
                Column(
                  children: [
                    Text('Change State'),
                    Switch(
                      value: elevatedBtnSwitchState,
                      onChanged: (newState) {
                        setState(() {
                          elevatedBtnSwitchState = !elevatedBtnSwitchState;
                        });
                      },
                    ),
                  ],
                )
              ],
            ),
            Divider(),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                OutlinedButton(
                  child: Text('Outlined Button'),
                  onPressed: outlinedBtnState ? () {} : null,
                  style: ButtonStyle(
                      foregroundColor: MaterialStateProperty.resolveWith(
                    (states) {
                      if (states.contains(MaterialState.disabled)) {
                        return Colors.grey;
                      } else {
                        return Colors.red;
                      }
                    },
                  ), side: MaterialStateProperty.resolveWith((states) {
                    if (states.contains(MaterialState.disabled)) {
                      return BorderSide(color: Colors.grey);
                    } else {
                      return BorderSide(color: Colors.red);
                    }
                  })),
                ),
                Column(
                  children: [
                    Text('Change State'),
                    Switch(
                      value: outlinedBtnState,
                      onChanged: (newState) {
                        setState(() {
                          outlinedBtnState = !outlinedBtnState;
                        });
                      },
                    ),
                  ],
                )
              ],
            ),
          ],
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)


Fax*_*yev 8

这是在 Flutter 中禁用按钮的最简单方法是将null值分配给onPressed

ElevatedButton(
  style: ElevatedButton.styleFrom(
    primary: Colors.blue, // background
    onPrimary: Colors.white, // foreground
  ),
  onPressed: null,
  child: Text('ElevatedButton'),
),
Run Code Online (Sandbox Code Playgroud)


Cop*_*oad 7

设置

onPressed: null // disables click
Run Code Online (Sandbox Code Playgroud)

onPressed: () => yourFunction() // enables click
Run Code Online (Sandbox Code Playgroud)

  • 在此解决方案中,“onPressed”的值始终是一个函数,因此按钮呈现为“可单击”,尽管如果设置了“isEnabled”属性,它将忽略单击事件。要真正禁用该按钮,请使用 ```RaishedButton(onPressed: isEnabled ? _handleClick : null ``` (2认同)

Tab*_*aba 6

对于禁用任何按钮在扑如FlatButtonRaisedButtonMaterialButtonIconButton等所有你需要做的是设置onPressedonLongPress属性。下面是一些按钮的一些简单示例:

扁平按钮(启用)

FlatButton(
  onPressed: (){}, 
  onLongPress: null, // Set one as NOT null is enough to enable the button
  textColor: Colors.black,
  disabledColor: Colors.orange,
  disabledTextColor: Colors.white,
  child: Text('Flat Button'),
),
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明 在此处输入图片说明

扁平按钮(禁用)

FlatButton(
  onPressed: null,
  onLongPress: null,
  textColor: Colors.black,
  disabledColor: Colors.orange,
  disabledTextColor: Colors.white,
  child: Text('Flat Button'),
),
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

凸起按钮(启用)

RaisedButton(
  onPressed: (){},
  onLongPress: null, // Set one as NOT null is enough to enable the button
  // For when the button is enabled
  color: Colors.lightBlueAccent,
  textColor: Colors.black,
  splashColor: Colors.blue,
  elevation: 8.0,

  // For when the button is disabled
  disabledTextColor: Colors.white,
  disabledColor: Colors.orange,
  disabledElevation: 0.0,

  child: Text('Raised Button'),
),
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

凸起按钮(禁用)

RaisedButton(
  onPressed: null,
  onLongPress: null,
  // For when the button is enabled
  color: Colors.lightBlueAccent,
  textColor: Colors.black,
  splashColor: Colors.blue,
  elevation: 8.0,

  // For when the button is disabled
  disabledTextColor: Colors.white,
  disabledColor: Colors.orange,
  disabledElevation: 0.0,

  child: Text('Raised Button'),
),
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

图标按钮(启用)

IconButton(
  onPressed: () {},
  icon: Icon(Icons.card_giftcard_rounded),
  color: Colors.lightBlueAccent,
            
  disabledColor: Colors.orange,
),
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明 在此处输入图片说明

图标按钮(禁用)

IconButton(
  onPressed: null,
  icon: Icon(Icons.card_giftcard_rounded),
  color: Colors.lightBlueAccent,
            
  disabledColor: Colors.orange,
),
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

注意:某些按钮例如IconButton只有onPressed属性。


Ama*_*rdo 6

有两种方法可以做到这一点:

1- /sf/answers/3454820351/

2-您可以使用 MaterialStatesController:

final _statesController = MaterialStatesController();
Run Code Online (Sandbox Code Playgroud)

然后将状态更改为:

_statesController.update(
   MaterialState.disabled,
   true, // or false depending on your logic
);
Run Code Online (Sandbox Code Playgroud)

在你的按钮上

ElevatedButton(
    onPressed: _onPressed,
    statesController: _statesController,
    child: Text("Awesome"),
),
Run Code Online (Sandbox Code Playgroud)

此外,您可以在禁用时更改按钮样式:在主题设置中:

....
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
              ),
            ),
...
Run Code Online (Sandbox Code Playgroud)


Vic*_*khe 5

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

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

只需onPressed如下所示设置属性

onPressed : null返回禁用的小部件

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