如何在Flutter Widget(Center Widget)的child属性内使用条件语句


130

到目前为止,每当我需要在Widget中使用条件语句时,我都会执行以下操作(使用Center和Containers作为简化的虚拟示例):

new Center(
  child: condition == true ? new Container() : new Container()
)

虽然当我尝试使用if / else语句时,它将导致Dead代码警告:

new Center(
  child: 
    if(condition == true){
      new Container();
    }else{
      new Container();
    }
)

有趣的是,我尝试使用switch case语句,它给出了相同的警告,因此我无法运行代码。我是在做错什么,还是在不颤抖地认为代码无效的情况下不能使用if / else或switch语句?


1
如果要在其中实例化窗口小部件的位置插入一个块,则可能最好在类方法中构建窗口小部件
aziza '18

Center(child:Builder(builder:(context){if(true)return widget1(); else return widget2();}))
Avnish kumar

Answers:


157

实际上,您可以在Dart / Flutter中使用if/elseswitch和任何其他语句内联。

使用立即匿名功能

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

9
我认为,这是最完整的答案,谢谢@orangesherbert
Oniya Daniel

2
请注意,如果有人卡住了,如果您正在使用Provider来根据全局状态更改来重建窗口小部件,并且您正在通过“ Provider.of”来获取数据,则在执行其他一些操作来重建窗口小部件之前,可能不会重新评估条件语句。您需要通过返回到Widget构建函数的“消费者”来获取条件变量,然后应在全局状态更改时正确地重新评估条件语句。
马修·赖德out

飞镖/颤振最佳实践的最佳方法之一
Kohls

72

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

1
这应该是正确的答案!谢谢您的澄清,它对我有帮助!
Slamit

34

为了便于记录,Dart 2.3增加了在Collection文字中使用if / else语句的功能。现在,可以通过以下方式完成此操作:

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

Flutter问题#28181-列表中的内联条件渲染


我有dart 2.5,但是在上面的代码上运行时出错。它说`该代码必须与早期版本兼容。尝试更新SDK约束
`

埃姆

是否添加for循环功能?如果可以的话,如何执行呢?
princebillyGK


不适用于单个窗口小部件,例如AppBar -> leading:child:
Alex Vang

33

在这种情况下,我将使用三元运算符进行命令:

child: condition ? Container() : Center()

并尝试避免以下形式的代码:

if (condition) return A else return B

这比三元运算符更为冗长。

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

使用构建器小部件

生成器插件是为允许使用封闭时,需要一个子控件:

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

任何时候您需要逻辑来构建窗口小部件时它都很方便,它避免了创建专用功能的需要。

您将Builder小部件用作子级,并在其builder方法中提供逻辑:

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

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

我也同意应该从UI代码中提取逻辑,但是当它真正是UI逻辑时,将其保留在那里有时更容易理解。


这对我来说非常适合抽屉项目的单击和更新正文
快速学习者

22

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

非常整洁,因为您可以在多个小部件中重复使用颜色选择器功能。


1
我尝试了这个,并为我工作了确切的方法。谢谢
Ajay Kumar

18

我个人将if / else语句用于带有此类block语句的儿童。它仅在以上Dart版本2.3.0上支持。

如果别的

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

如果/否则,如果

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

17

您可以简单地使用条件语句 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(...),
 ],
)

1
如果没有其他条件怎么办?在列,称== B C:空将无法正常工作
cwhisperer

1
您可以简单地使用SizedBox.shrick()作为第二个小部件。更新答案。
Afinas EM

1
如果是列,则可以直接使用if条件,而无需其他情况:'if('condition')widget()'
Afinas EM

10

这是解决方案。我已经解决了。这是代码

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

如何使用它
ardi

6

如果您使用小部件列表,则可以使用以下方法:

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

健康)状况?Text(“ True”):null,这会在运行时执行时在控制台中产生错误Asertion false
exequielc

@exequielc必须添加.where(notNull).toList()和WidgetList的末尾,以及方法bool notNull(Object o)=> o!= null;。尝试整个示例...
Tobias

1
从Dart 2.3开始,有条件地在列表中包括小部件,您可以使用:[Text(“ Hello”),if(world)Text(“ World”)]
Brett Sutton

4

另一种选择:对于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];
  }
}

3

大声笑了几个月后使用?:我发现我可以使用它:

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

2

这是一篇很棒的文章和对话。我尝试使用所述的三元运算符。但是代码无法正常工作,导致出现上述错误。

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

上面的三元示例是小姐率先。Dart会返回一个错误,返回一个null而不是小部件。您不能返回null。正确的方法是返回小部件:

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

为了使三元组工作,您需要返回一个Widget。如果您不想返回任何内容,则可以返回一个空容器。

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

祝好运。


2

带按钮

bool _paused = false;

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

1

****您也可以使用此方法使用条件** **

 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
            )

            ),
          ) 
        ),

1

如果要进行条件渲染,则可能会发生以下情况:

Column(
   children: <Widget>[
     if (isCondition == true)
        Text('The condition is true'),
   ],
 );

但是,如果您想使用第三级(如果不是)条件,该怎么办?当子窗口小部件是多层时。

您可以将其用于解决方案flutter_conditional_rendering flutter包,该包可以增强条件渲染,支持if-else和switch条件。

如果-其他条件:

Column(
      children: <Widget>[
        Conditional.single(
          context: context,
          conditionBuilder: (BuildContext context) => someCondition == true,
          widgetBuilder: (BuildContext context) => Text('The condition is true!'),
          fallbackBuilder: (BuildContext context) => Text('The condition is false!'),
        ),
      ],
    );

切换条件:

Column(
      children: <Widget>[
        ConditionalSwitch.single<String>(
          context: context,
          valueBuilder: (BuildContext context) => 'A',
          caseBuilders: {
            'A': (BuildContext context) => Text('The value is A!'),
            'B': (BuildContext context) => Text('The value is B!'),
          },
          fallbackBuilder: (BuildContext context) => Text('None of the cases matched!'),
        ),
      ],
    );

如果要有条件地呈现窗口小部件列表,(List<Widget>)而不是单个窗口小部件。使用Conditional.list()ConditionalSwitch.list()!


1

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

非常有用,谢谢分享!
Petro

1

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

(condition) ? statement1 : statement2

如果conditiontrue为true,statement1则将执行否则statement2

举一个实际的例子

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

请记住,如果你要使用nullWidget2是更好地使用SizedBox.shrink(),因为一些家长控件会得到一个后抛出一个异常null的孩子。


-4

仅在振动小部件时

if(bool = true) Container(

child: ....

),

OR

if(bool = true) Container(

child: ....

) else new Container(child: lalala),
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.