到目前为止,每当我需要在 Widget 中使用条件语句时,我都会执行以下操作(使用 Center 和 Containers 作为简化的虚拟示例):
new Center(
child: condition == true ? new Container() : new Container()
)
虽然当我尝试使用 if/else 语句时,它会导致死代码警告:
new Center(
child:
if(condition == true){
new Container();
}else{
new Container();
}
)
有趣的是,我尝试使用 switch case 语句,它给了我同样的警告,因此我无法运行代码。我是在做错什么,或者是因为人们无法使用 if/else 或 switch 语句而不会颤抖,认为有死代码?
实际上,您可以在 dart / flutter 中使用 if/else
和 switch
以及任何其他内联语句。
使用即时匿名函数
class StatmentExample extends StatelessWidget {
Widget build(BuildContext context) {
return Text((() {
if(true){
return "tis true";}
return "anything but true";
})());
}
}
即将你的陈述包装在一个函数中
(() {
// your code here
}())
我强烈建议不要将过多的逻辑直接放在你的 UI '标记'中,但我发现 Dart 中的类型推断需要做一些工作,所以它有时在这样的场景中很有用。
使用三元运算符
condition ? Text("True") : null,
在集合中使用 If 或 For 语句或展开运算符
children: [
...manyItems,
oneItem,
if(canIKickIt)
...kickTheCan
for (item in items)
Text(item)
使用方法
child: getWidget()
Widget getWidget() {
if (x > 5) ...
//more logic here and return a Widget
重新定义 switch 语句
作为三元运算符的另一种替代方法,您可以创建 switch 语句的函数版本,例如在以下帖子 https://stackoverflow.com/a/57390589/1058292 中。
child: case2(myInput,
{
1: Text("Its one"),
2: Text("Its two"),
}, Text("Default"));
我个人在这种块语句中使用 if/else 语句。它仅支持 Dart 2.3.0 以上版本。
如果别的
Column(
children: [
if (_selectedIndex == 0) ...[
DayScreen(),
] else ...[
StatsScreen(),
],
],
),
如果/否则如果
Column(
children: [
if (_selectedIndex == 0) ...[
DayScreen(),
] else if(_selectedIndex == 1)...[
StatsScreen(),
],
],
),
多个小部件示例
Column(
children: [
if (_selectedIndex == 0) ...[
DayScreen(),
AboutScreen(),
InfoScreen(),
] else if(_selectedIndex == 1)...[
HomeScreen(),
StatsScreen(),
],
],
),
...[]
技巧太棒了。这是一个没有其他答案提到的细节,但是如果您想有条件地添加多个小部件,它非常有用。
在 Dart 中,if/else
和 switch
是语句而不是表达式。它们不返回值,因此您不能将它们传递给构造函数参数。如果您的构建方法中有很多条件逻辑,那么尝试简化它是一个好习惯。例如,您可以将自包含逻辑移动到方法中,并使用 if/else
语句来初始化您以后可以使用的局部变量。
使用方法和 if/else
Widget _buildChild() {
if (condition) {
return ...
}
return ...
}
Widget build(BuildContext context) {
return new Container(child: _buildChild());
}
使用 if/else
Widget build(BuildContext context) {
Widget child;
if (condition) {
child = ...
} else {
child = ...
}
return new Container(child: child);
}
在这种情况下,我建议使用三元运算符:
child: condition ? Container() : Center()
并尽量避免以下形式的代码:
if (condition) return A else return B
这比三元运算符不必要地冗长。
但如果需要更多逻辑,您也可以:
使用生成器小部件
Builder widget 用于在需要子小部件时允许使用闭包:
一个柏拉图式的小部件,它调用一个闭包来获取它的子小部件。
每当您需要逻辑来构建小部件时都很方便,它避免了创建专用函数的需要。
您将 Builder 小部件用作子小部件,并在其 builder
方法中提供您的逻辑:
Center(
child: Builder(
builder: (context) {
// any logic needed...
final condition = _whateverLogicNeeded();
return condition
? Container();
: Center();
}
)
)
Builder 提供了一个方便的地方来保存创建逻辑。它比 atreeon 提出的直接匿名函数更直接。
我也同意应该从 UI 代码中提取逻辑,但是当它真的是 UI 逻辑时,有时将其保留在那里更清晰。
作为记录,Dart 2.3 添加了在 Collection 文字中使用 if/else 语句的能力。现在通过以下方式完成:
return Column(children: <Widget>[
Text("hello"),
if (condition)
Text("should not render if false"),
Text("world")
],);
Flutter Issue #28181 - Inline conditional rendering in list
AppBar -> leading:
或 child:
这样的单个小部件
我发现使用条件逻辑构建 Flutter UI 的一种简单方法是将逻辑保留在 UI 之外。这是一个返回两种不同颜色的函数:
Color getColor(int selector) {
if (selector % 2 == 0) {
return Colors.blue;
} else {
return Colors.blueGrey;
}
}
该函数用于设置 CircleAvatar 的背景。
new ListView.builder(
itemCount: users.length,
itemBuilder: (BuildContext context, int index) {
return new Column(
children: <Widget>[
new ListTile(
leading: new CircleAvatar(
backgroundColor: getColor(index),
child: new Text(users[index].name[0])
),
title: new Text(users[index].login),
subtitle: new Text(users[index].name),
),
new Divider(height: 2.0),
],
);
},
);
非常整洁,因为您可以在多个小部件中重复使用颜色选择器功能。
您可以简单地使用条件语句 a==b?c:d
例如 :
Container(
color: Colors.white,
child: ('condition')
? Widget1(...)
: Widget2(...)
)
我希望你明白了。
假设如果没有其他条件,您可以使用 SizedBox.shrink()
Container(
color: Colors.white,
child: ('condition')
? Widget1(...)
: SizedBox.shrink()
)
如果是列则不需要写 ?:
运算符
Column(
children: <Widget>[
if('condition')
Widget1(...),
],
)
除了三元运算符之外,如果您需要在条件语句之前执行操作,您还可以使用 Builder
小部件。
Builder(builder: (context) {
/// some operation here ...
if(someCondition) {
return Text('A');
}
else {
return Text('B');
}
})
使用几个月后大声笑?:我刚刚发现我可以使用这个:
Column(
children: [
if (true) Text('true') else Text('false'),
],
)
这是解决方案。我已经修好了。这是代码
child: _status(data[index]["status"]),
Widget _status(status) {
if (status == "3") {
return Text('Process');
} else if(status == "1") {
return Text('Order');
} else {
return Text("Waiting");
}
}
如果您使用小部件列表,则可以使用:
class HomePage extends StatelessWidget {
bool notNull(Object o) => o != null;
@override
Widget build(BuildContext context) {
var condition = true;
return Scaffold(
appBar: AppBar(
title: Text("Provider Demo"),
),
body: Center(
child: Column(
children: <Widget>[
condition? Text("True"): null,
Container(
height: 300,
width: MediaQuery.of(context).size.width,
child: Text("Test")
)
].where(notNull).toList(),
)),
);
}
}
另一种选择:对于像'switch's
'这样的语句,有很多条件,我喜欢使用地图:
return Card(
elevation: 0,
margin: EdgeInsets.all(1),
child: conditions(widget.coupon)[widget.coupon.status] ??
(throw ArgumentError('invalid status')));
conditions(Coupon coupon) => {
Status.added_new: CheckableCouponTile(coupon.code),
Status.redeemed: SimpleCouponTile(coupon.code),
Status.invalid: SimpleCouponTile(coupon.code),
Status.valid_not_redeemed: SimpleCouponTile(coupon.code),
};
无需接触条件语句即可更轻松地向条件列表添加/删除元素。
另一个例子:
var condts = {
0: Container(),
1: Center(),
2: Row(),
3: Column(),
4: Stack(),
};
class WidgetByCondition extends StatelessWidget {
final int index;
WidgetByCondition(this.index);
@override
Widget build(BuildContext context) {
return condts[index];
}
}
****您也可以使用此方法使用条件** **
int _moneyCounter = 0;
void _rainMoney(){
setState(() {
_moneyCounter += 100;
});
}
new Expanded(
child: new Center(
child: new Text('\$$_moneyCounter',
style:new TextStyle(
color: _moneyCounter > 1000 ? Colors.blue : Colors.amberAccent,
fontSize: 47,
fontWeight: FontWeight.w800
)
),
)
),
用一个按钮
bool _paused = false;
CupertinoButton(
child: _paused ? Text('Play') : Text('Pause'),
color: Colors.blue,
onPressed: () {
setState(() {
_paused = !_paused;
});
},
),
最简单的方法:
// the ternary operator:
<conditon>
? Widget1(...)
: Widget2(...)
// Or:
if (condition)
Widget1(...)
// With else/ if else
if (condition1)
Widget1(...)
else if (condition2)
Widget2(...)
else
Widget3(...),
如果你想为一个条件渲染 MULTIPLE WIDGETS,你可以使用扩展运算符:
if (condition) ...[
Widget1(...),
Widget2(...),
],
// with else / else if:
if (condition1) ...[
Widget1(...),
Widget2(...),
]
else if(condition2)...[
Widget3(...),
Widget4(...),
]
else ...[
Widget3(...),
Widget4(...),
],
这是一篇很棒的文章和对话。我尝试按照描述使用三元运算符。但是代码不起作用导致上述错误。
Column(children: [ condition? Text("True"): null,],);
上面的三元示例是未命中领先。 Dart 将返回一个错误,即返回 null 而不是小部件。你不能返回空值。正确的方法是返回一个小部件:
Column(children: [ condition? Text("True"): Text("false"),],);
为了使三元组工作,您需要返回一个小部件。如果您不想退回任何东西,您可以退回一个空容器。
Column(children: [ condition? Text("True"): Container(),],);
祝你好运。
dart 中的条件语句可以使用三元运算符,使用很简单
(condition) ? statement1 : statement2
如果 condition
为真,则 statement1
将被执行,否则 statement2
。
举个实际例子
Center(child: condition ? Widget1() : Widget2())
请记住,如果您要将 null
用作 Widget2
,最好使用 SizedBox.shrink()
,因为某些父窗口小部件在获得 null
子窗口后会抛出异常。
编辑:我不再推荐我在下面发布的解决方案,因为我意识到使用这种方法,生成了真实结果的孩子和虚假结果的孩子,但只使用了一个,这不必要地减慢了代码。
以前的答案:
在我的应用程序中,我创建了一个 WidgetChooser
小部件,因此我可以在没有条件逻辑的小部件之间进行选择:
WidgetChooser(
condition: true,
trueChild: Text('This widget appears if the condition is true.'),
falseChild: Text('This widget appears if the condition is false.'),
);
这是 WidgetChooser
小部件的来源:
import 'package:flutter/widgets.dart';
class WidgetChooser extends StatelessWidget {
final bool condition;
final Widget trueChild;
final Widget falseChild;
WidgetChooser({@required this.condition, @required this.trueChild, @required this.falseChild});
@override
Widget build(BuildContext context) {
if (condition) {
return trueChild;
} else {
return falseChild;
}
}
}
您可以在以下人员中使用构建器:我考虑了一个条件,我们可以将图像 url 设置为 null,因此如果为 null,我将显示一个缩小大小的框,因为它没有属性,一个完全无效的小部件。
Builder(builder: (BuildContext context) {
if (iconPath != null) {
return ImageIcon(
AssetImage(iconPath!),
color: AppColors.kPrimaryColor,
);
} else {
return SizedBox.shrink();
}
})
Flutter 中的条件渲染可以通过 proviso 包轻松完成。它有一套全面的条件小部件和构建器,可以制作更易读和更简单的条件语句代码。
API 和助手包括但不限于:
条件小部件和构建器:
ConditionWidget(
condition: starred,
widget: Icon(
Icons.favorite
),
fallback: fallbackWidget
)
ConditionBuilder(
condition: (_) => someCondition,
trueBuilder: (_) => trueWidget,
fallbackBuilder: (_) => fallbackWidget
)
切换案例条件:
SwitchCaseBuilder.widget<String>(
context: context,
condition: (_) => '1',
caseBuilders: {'1': (_) => someWidget(), '2': (_) => someWidget()},
fallbackBuilder: (_) => fallbackWidget,
);
甚至是有条件的父小部件
ConditionalWrap(
shouldWrap: shouldWrapChildInParent,
child: Container(),
parentBuilder: (child) => Container(
child: child,
),
)
API 支持单个或多个小部件呈现。欢迎您试一试。
我更喜欢使用 Map
Map<String, Widget> pageSelector = {
"login": Text("Login"),
"home": Text("Home"),
}
在构建函数中,我像这样将密钥传递给地图
new Center(
child: pageSelector["here pass the key"] ?? Text("some default widget"),
)
或另一种解决方案是使用简单的功能
Widget conditionalWidget(int numberToCheck){
switch(numberToCheck){
case 0: return Text("zero widget");
case 1: return Text("one widget");
case 2: return Text("two widget");
case 3: return Text("three widget");
default: return Text("default widget");
}
并在构建函数内部传递小部件的数量或任何其他参数来检查
new Center(
child: conditionalWidget(pageNumber),
)
child: Container(
child: isFile == true ?
Image.network(pathfile, width: 300, height: 200, fit: BoxFit.cover) :
Text(message.subject.toString(), style: TextStyle(color: Colors.white),
),
),
我不知道这是否是一个好习惯,但我正在使用:
class StatmentExample extends StatelessWidget {
Widget build(BuildContext context) {
return pageValue==1 ? Page1():pageValue== 2? Page2():pageValue==3 ? Page3():Page4();
}
}
像这样做
Widget showIf(bool shouldShow, Widget widget) {
if (shouldShow) {
return widget;
} else {
return Container();
}}
所以当你想展示一些有条件的东西时,你确实喜欢说
Column(children: [showIf(myConditionIsTrue, myComplexWidget)])
有两种可能性:
如果您只使用一个小部件
解决方案=>
Visibility(
visible: condition == true,
child: Text(""),
),
OR
Offstage(
offstage: condition == false,
child: Text(""),
),
如果您使用两个或更多小部件
解决方案=>
bool _visibility = false;
isVisible?
Widget1
:
WIdget2
更好的方法
Column(
children: [
if (firstCondition == true) ...[
DayScreen(),
] else if(secondCondition == true)...[
StatsScreen(),
], else...[
StatsScreen(),
],
],
),
在我看来,我更喜欢的最好和最简洁的方法是创建一个辅助 typedef 函数类 coditional_widget.dart。
typedef IfWidget = List<Widget> Function(bool, Widget);
typedef IfElseWidget = Widget Function(bool, Widget, Widget);
typedef ElseEmptyWidget = Widget Function(bool, Widget);
IfWidget ifTrueWidget =
(bool condition, Widget child) => [if (condition) child];
IfElseWidget ifElseWidget =
(bool condition, Widget isTrueChild, Widget isFalseChild) =>
condition ? isTrueChild : isFalseChild;
ElseEmptyWidget elseEmptyWidget = (bool condition, Widget isTrueChild) =>
condition ? isTrueChild : const SizedBox.shrink();
如何使用它
// IfWidget
** Row/ Column / Wrap child etc.
children: <Widget>[
...ifWidget(title != null, Text('Only Display for True Conditon')),
]
// elseEmptyWidget
** Row/ Column / Wrap child etc.
children: <Widget>[
elseEmptyWidget(title!=null,Text('Only Display for True Conditon')),
]
// ifElseWidget
** Row/ Column / Wrap child etc.
children: <Widget>[
ifElseWidget(true,Text('Only Display for True Conditon'),Text('Only Display for false Conditon')),
]
只有几个你可以添加更多
仅当振动小部件
if(bool = true) Container(
child: ....
),
OR
if(bool = true) Container(
child: ....
) else new Container(child: lalala),
不定期副业成功案例分享
null
或空Container()
?