我刚开始掌握Flutter的窍门,但我不知道如何设置按钮的启用状态。
从文档中,它说将onPressed设置为null来禁用按钮,并给它一个值来启用它。如果按钮在生命周期中继续处于相同的状态,这是没问题的。
我得到的印象是,我需要创建一个自定义的有状态小部件,它将允许我以某种方式更新按钮的启用状态(或onPressed回调)。
我的问题是我该怎么做?这似乎是一个非常简单的要求,但我在文档中找不到任何关于如何做到这一点的东西。
谢谢。
我刚开始掌握Flutter的窍门,但我不知道如何设置按钮的启用状态。
从文档中,它说将onPressed设置为null来禁用按钮,并给它一个值来启用它。如果按钮在生命周期中继续处于相同的状态,这是没问题的。
我得到的印象是,我需要创建一个自定义的有状态小部件,它将允许我以某种方式更新按钮的启用状态(或onPressed回调)。
我的问题是我该怎么做?这似乎是一个非常简单的要求,但我在文档中找不到任何关于如何做到这一点的东西。
谢谢。
当前回答
见下面的可能的解决方案,添加'ValueListenableBuilder'的'TextEditingValue'监听控制器(TextEditingController),并返回你的函数调用如果控制器。文本不为空,如果为空则返回'null'。
// valuelistenablebuilder环绕按钮
ValueListenableBuilder<TextEditingValue>(
valueListenable: textFieldController,
builder: (context, ctrl, __) => ElevatedButton(
onPressed: ctrl.text.isNotEmpty ? yourFunctionCall : null,
child: Text(
'SUBMIT',
style: GoogleFonts.roboto(fontSize: 20.0),
),
),
),
特克斯菲尔德
TextField(controller: textFieldController,
onChanged: (newValue) {
textFieldText = newValue;
},
),
生成器将监听控制器,并仅在使用文本字段时启用按钮。我希望这能回答问题。让我知道…
其他回答
有两种方法:
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
),
),
...
在我看来,这是最简单的方法:
RaisedButton(
child: Text("PRESS BUTTON"),
onPressed: booleanCondition
? () => myTapCallback()
: null
)
我认为您可能需要引入一些帮助函数来构建按钮,以及一个有状态的小部件以及一些要关闭的属性。
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();
};
}
}
根据文件:
如果onPressed回调为空,则该按钮将被禁用 默认情况下类似于disabledColor中的平面按钮。
所以,你可以这样做:
RaisedButton(
onPressed: calculateWhetherDisabledReturnsBool() ? null : () => whatToDoOnPressed,
child: Text('Button text')
);
这个答案是基于更新的按钮TextButton/ElevatedButton/OutlinedButton颤振2.x
不过,按钮是基于onPressed属性启用或禁用的。如果该属性为空,则按钮将被禁用。如果你将函数分配给onPressed,那么按钮将被启用。 在下面的代码片段中,我展示了如何启用/禁用按钮,并相应地更新它的样式。
这篇文章也说明了如何将不同的风格应用到新的 颤振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;
});
},
),
],
)
],
),
],
),
),
);
}
}