【问题标题】:How to use conditional statement within child attribute of a Flutter Widget (Center Widget)如何在 Flutter Widget(Center Widget)的子属性中使用条件语句
【发布时间】:2018-09-17 16:27:52
【问题描述】:

到目前为止,每当我需要在 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 语句而不会颤抖,认为有死代码?

【问题讨论】:

  • 如果你想在应该实例化小部件的地方插入一个块,你最好在类方法中构建你的小部件
  • Center(child:Builder(builder:(context){ if(true) return widget1(); else return widget2(); }) )

标签: flutter if-statement dart conditional-statements


【解决方案1】:

实际上你可以使用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"));

【讨论】:

  • 如果有人卡住,请注意,如果您使用 Provider 在全局状态更改时重建您的小部件,并且您通过“Provider.of”获取数据,您的条件语句可能不会重新评估,直到其他一些操作重建您的小部件。您需要通过返回到 Widget 构建函数的“Consumer”获取您的条件变量,然后您的条件语句应该在全局状态更改时正确地重新评估。
  • dart/flutter 中的最佳实践之一
  • 三元码哪一个更好?使用null 或空Container() ?
  • 你可以把样式放在哪里,通过即时匿名功能?例如:样式:TextStyle(颜色:Colors.white),
  • 我收到一个错误,即 Column 不能包含三元和空 Container() 的空值是一种解决方法
【解决方案2】:

我个人在这种块语句中使用 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(),
        ],
    ],
 ),

【讨论】:

  • ...[] 的把戏太棒了。这是一个没有其他答案提到的细节,但是如果您想有条件地添加多个小部件,它非常有用。
  • 有人知道这是从哪个版本的颤振开始的吗?
  • @ShadyMohamedSherif 您现在使用的是哪个版本?我从 1.17 开始使用颤振,从那时起它就已经开始工作了。这没什么特别的,它只是传播一个小部件列表。
  • 我希望我以前知道这种方式。非常感谢:)
【解决方案3】:

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

【讨论】:

  • 这应该是正确答案!感谢您的澄清,它帮助了我!
  • 如果你有一棵很深的树,并且有条件地想在树中渲染一些东西怎么办?复制?还是我必须以某种方式拆分树?
【解决方案4】:

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

child: condition ? Container() : Center()

并尽量避免以下形式的代码:

if (condition) return A else return B

这比三元运算符不必要地冗长。

但如果需要更多逻辑,您也可以:

使用 Builder 小部件

Builder widget 用于在需要子窗口小部件时允许使用闭包:

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

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

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

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

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

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

【讨论】:

  • 这对我来说非常适合抽屉项目点击和更新正文
【解决方案5】:

作为记录,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

【讨论】:

  • 我有 dart 2.5 但在代码上方运行时出错。它说`此代码必须与早期版本兼容。尝试更新 SDK 约束`
  • emmm,有意思~
  • 他们是否添加了 for 循环功能?如果可以,如何实现?
  • 不适用于 AppBar -&gt; leading:child: 等单个小部件
【解决方案6】:

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

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

【讨论】:

  • 我试过这个并以确切的方式为我工作。谢谢
【解决方案7】:

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

【讨论】:

  • 如果没有其他条件怎么办?在列中,说 a==b?c:null 将不起作用
  • 您可以简单地使用 SizedBox.shrick() 作为第二个小部件。更新答案。
  • 如果是列则可以直接使用if条件,不用else case:`if('condition') widget()'
【解决方案8】:

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

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

【讨论】:

  • 如何使用
【解决方案9】:

使用几个月后大声笑:我才发现我可以使用这个:

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

【讨论】:

    【解决方案10】:

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

    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 您必须添加 .where(notNull).toList() 和 WidgetList 的末尾以及方法 bool notNull(Object o) => o != null;。尝试整个示例...
    • 从 Dart 2.3 开始,有条件地在列表中包含一个小部件,您可以使用:[Text("Hello"), if(world) Text("World")]
    【解决方案11】:

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

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

    【讨论】:

    • 很好的答案!如果您有一个 if-else 条件三元运算符就足够了,但如果您有多个 if-else if-else 条件或 switch case,那么 Builder 小部件应该是一个合适的解决方案。
    【解决方案12】:

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

    【讨论】:

      【解决方案13】:

      ****你也可以通过这个方法使用条件** **

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

      【讨论】:

      • 这是对在属性中使用条件最清晰的解释
      【解决方案14】:

      带按钮

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

      【讨论】:

        【解决方案15】:

        这是一篇很棒的文章和对话。我尝试按照描述使用三元运算符。但是代码不起作用导致上述错误。

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

        上面的三元示例是未命中领先。 Dart 将返回一个错误,即返回 null 而不是小部件。你不能返回空值。正确的方法是返回一个小部件:

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

        为了使三元组工作,您需要返回一个小部件。如果您不想退回任何东西,您可以退回一个空容器。

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

        祝你好运。

        【讨论】:

          【解决方案16】:

          在flutter中如果你想做条件渲染,你可以这样做:

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

          但是,如果您想使用第三(if-else)条件怎么办?当子小部件是多层时。

          您可以将其用于其解决方案flutter_conditional_rendering 一个增强条件渲染、支持 if-else 和 switch 条件的颤振包。

          If-Else 条件:

          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&lt;Widget&gt;) 而不是单个。使用Conditional.list()ConditionalSwitch.list()!

          【讨论】:

            【解决方案17】:

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

            (condition) ? statement1 : statement2
            

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

            举个实际例子

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

            请记住,如果您要将null 用作Widget2,最好使用SizedBox.shrink(),因为某些父窗口小部件在获得null 子窗口后会抛出异常。

            【讨论】:

              【解决方案18】:

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


              以前的答案:

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

              【讨论】:

              • 有趣! ?
              【解决方案19】:

              您可以在以下人员配置中使用构建器: 我考虑了一个条件,我们可以将图像 url 设为 null,因此如果为 null,我会显示一个缩小大小的框,因为它没有完全无效的小部件的属性。

              Builder(builder: (BuildContext context) {
                if (iconPath != null) {
                  return ImageIcon(
                    AssetImage(iconPath!),
                    color: AppColors.kPrimaryColor,
                  );
                } else {
                  return SizedBox.shrink();
                }
              })
              

              【讨论】:

                【解决方案20】:

                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 支持单个或多个小部件呈现。 欢迎您试一试。

                【讨论】:

                  【解决方案21】:

                  我更喜欢使用 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),
                  )
                  

                  【讨论】:

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

                    【讨论】:

                    • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助、质量更好,并且更有可能吸引投票。
                    【解决方案23】:

                    我不知道这是否是一个好习惯,但我正在使用:

                    class StatmentExample extends StatelessWidget {
                      Widget build(BuildContext context) {
                        return pageValue==1 ? Page1():pageValue== 2? Page2():pageValue==3 ? Page3():Page4();
                      }
                    }
                    

                    【讨论】:

                      【解决方案24】:

                      这样做

                      Widget showIf(bool shouldShow, Widget widget) {
                      if (shouldShow) {
                        return widget;
                      } else {
                        return Container();
                      }}
                      

                      所以当你想展示一些有条件的东西时,你确实喜欢说

                      Column(children: [showIf(myConditionIsTrue, myComplexWidget)])
                      

                      【讨论】:

                        【解决方案25】:

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

                        See the documentation here

                        【讨论】:

                          【解决方案26】:

                          仅当振动小部件时

                          if(bool = true) Container(
                          
                          child: ....
                          
                          ),
                          
                          OR
                          
                          if(bool = true) Container(
                          
                          child: ....
                          
                          ) else new Container(child: lalala),
                          

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 2020-06-26
                            • 2019-10-24
                            • 2017-10-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2020-10-10
                            相关资源
                            最近更新 更多