如何在颤振小部件(中心小部件)的子属性中使用条件语句

到目前为止,当我需要在小部件中使用条件语句时,我已经做了以下工作(使用中心和容器作为简化的虚拟示例):

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或开关语句而不颤振认为有死代码?

481606 次浏览

在Dart中,if/elseswitch是语句而不是表达式。它们不返回值,所以不能将它们传递给构造函数参数。如果您的构建方法中有很多条件逻辑,那么尝试简化它是一个很好的实践。例如,你可以将自包含逻辑移动到方法中,并使用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);
}

我发现使用条件逻辑构建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),
],
);
},
);

非常整洁,因为你可以在几个小部件中重用你的颜色选择器函数。

这是解决方案。 我已经修好了。下面是代码

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
)


),
)
),

实际上,你可以使用if/elseswitch和任何其他语句内联在dart / flutter。

使用立即匿名函数

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"));

为了记录,Dart 2.3增加了在Collection字面量中使用if/else语句的能力。这是现在完成以下方式:

return Column(children: <Widget>[
Text("hello"),
if (condition)
Text("should not render if false"),
Text("world")
],);

颤频Issue #28181 - Inline条件渲染列表

你可以简单地使用条件语句a==b?c:d

例如:

Container(
color: Colors.white,
child: ('condition')
? Widget1(...)
: Widget2(...)
)

我希望你明白了。

假设如果没有其他条件,你可以使用sizebox .shrink()

Container(
color: Colors.white,
child: ('condition')
? Widget1(...)
: SizedBox.shrink()
)

如果是列,则不需要写?:操作符

Column(
children: <Widget>[
if('condition')
Widget1(...),
],
)

我个人使用if/else语句在子语句中使用这种block语句。它只支持Dart 2.3.0以上版本。

If / else

Column(
children: [
if (_selectedIndex == 0) ...[
DayScreen(),
] else ...[
StatsScreen(),
],
],
),

If / else If

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(),
],
],
),

这是一篇很棒的文章和对话。我尝试使用如上所述的三元运算符。但是代码没有工作,导致了前面提到的错误。

Column(children: [ condition? Text("True"): null,],);

上面的三元例子是miss leading。Dart将响应一个错误,返回的是null而不是小部件。你不能返回null。正确的方法是返回一个小部件:

Column(children: [ condition? Text("True"): Text("false"),],);

为了让三元函数正常工作,您需要返回一个Widget。如果你不想返回任何东西,你可以返回一个空容器。

Column(children: [ condition? Text("True"): Container(),],);

祝你好运。

在这种情况下,我建议使用三元操作符:

child: condition ? Container() : Center()

并尽量避免使用如下形式的代码:

if (condition) return A else return B

这比三元运算符更冗长。

但如果需要更多的逻辑,你还可以:

使用Builder小部件

构建器部件意味着当需要子小部件时允许使用闭包:

一个柏拉图式的小部件,它调用闭包来获取它的子小部件。

在任何需要逻辑构建小部件的时候都很方便,它避免了创建专用函数的需要。

你使用Builder小部件作为子部件,你在它的builder方法中提供你的逻辑:

Center(
child: Builder(
builder: (context) {
// any logic needed...
final condition = _whateverLogicNeeded();
      

return condition
? Container();
: Center();
}
)
)

Builder为保存创建逻辑提供了一个方便的地方。它比atreeon提出的直接匿名函数更直接。

我也同意逻辑应该从UI代码中提取出来,但当它真的是UI逻辑时,有时保留它更容易读懂。

有一个按钮

bool _paused = false;


CupertinoButton(
child: _paused ? Text('Play') : Text('Pause'),
color: Colors.blue,
onPressed: () {
setState(() {
_paused = !_paused;
});
},
),

仅当部件振动时

if(bool = true) Container(


child: ....


),


OR


if(bool = true) Container(


child: ....


) else new Container(child: lalala),

编辑:我不再推荐我在下面发布的解决方案,因为我意识到使用这种方法,生成了真实结果的子结果和虚假结果的子结果,但只使用了一个,这不必要地降低了代码的速度。


之前的回答:

在我的应用程序中,我创建了一个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;
}
}
}

在使用了几个月后,我才发现我可以使用这个:

Column(
children: [
if (true) Text('true') else Text('false'),
],
)

你可以在dart中对条件语句使用三元运算符,它的使用很简单

(condition) ? statement1 : statement2

如果condition为真,则执行statement1,否则执行statement2

举一个实际的例子

Center(child: condition ? Widget1() : Widget2())

记住,如果你打算使用null作为Widget2,最好使用SizedBox.shrink(),因为一些父部件在获得null子部件后会抛出异常。

child: Container(
child: isFile == true ?
Image.network(pathfile, width: 300, height: 200, fit: BoxFit.cover) :
Text(message.subject.toString(), style: TextStyle(color: Colors.white),
),
),

除了三元操作符,如果在条件语句之前需要执行操作,还可以使用Builder小部件。

    Builder(builder: (context) {
/// some operation here ...
if(someCondition) {
return Text('A');
}
else {
return Text('B');
}
})
 

我不知道这是否是一个好的做法,但我正在使用:

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)])

你可以在以下操作中使用builder: 我已经考虑了一个条件,我们可以得到图像url为空,因此,如果为空,我显示一个缩小大小的盒子,因为它没有一个完全无效的小部件的属性

Builder(builder: (BuildContext context) {
if (iconPath != null) {
return ImageIcon(
AssetImage(iconPath!),
color: AppColors.kPrimaryColor,
);
} else {
return SizedBox.shrink();
}
})
Flutter中的条件渲染可以通过但书包轻松完成。 它有一组全面的条件小部件和构建器,可以使条件语句代码更具可读性和更简单

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<String, Widget>

Map<String, Widget> pageSelector = {
"login": Text("Login"),
"home": Text("Home"),
}

在build函数中,我像这样将键传递给map

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

如果你想避免使用If语句,你可以使用Flutter Visibility小部件

参考文档

有两种可能:

  1. 如果您只使用一个小部件

解决方案=比;

     Visibility(
visible: condition == true,
child: Text(""),
),
OR


Offstage(
offstage: condition == false,
child: Text(""),
),
  1. 如果您正在使用两个或更多小部件

解决方案=比;

      bool _visibility = false;
     

isVisible?
Widget1
:
WIdget2

最简单的方法:

// the ternary operator:
<conditon>
? Widget1(...)
: Widget2(...)


// Or:
if (condition)
Widget1(...)


// With else/ if else
if (condition1)
Widget1(...)
else if (condition2)
Widget2(...)
else
Widget3(...),

如果你想呈现一个条件下的多个小部件,你可以使用< >强传播算子< / >强(为此,你必须在堆栈小部件中):

if (condition) ...[
Widget1(...),
Widget2(...),
],


// with else / else if:
if (condition1) ...[
Widget1(...),
Widget2(...),
]
else if(condition2)...[
Widget3(...),
Widget4(...),
]
else ...[
Widget3(...),
Widget4(...),
],

更好的方法

 Column(
children: [
if (firstCondition == true) ...[
DayScreen(),
] else if(secondCondition == true)...[
StatsScreen(),
], else...[
StatsScreen(),
],
],
),

在我看来,我更喜欢的最好最干净的方式是创建一个helper类型定义函数类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')),
]

这只是几个你可以添加更多的

简单的方法:

使用构建器小部件

Center(
child: Builder(
builder: (context) {
if (a == b) {
return const Widget1();
} else {
return const Widget2();
}
},
),
)