ChatGPT解决这个技术问题 Extra ChatGPT

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

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

如果你想在应该实例化小部件的地方插入一个块,你最好在类方法中构建你的小部件
中心(孩子:建造者(建造者:(上下文){如果(真)返回小部件1();否则返回小部件2();}))

s
sidrao2006

实际上,您可以在 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"));

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

我个人在这种块语句中使用 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 开始使用颤振,从那时起它就已经开始工作了。这没什么特别的,它只是传播一个小部件列表。
我希望我以前知道这种方式。非常感谢 :)
J
Jonah Williams

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

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

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

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 逻辑时,有时将其保留在那里更清晰。


这对我来说非常适合抽屉项目点击和更新正文
W
Wiil

作为记录,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 -> leading:child: 这样的单个小部件
M
Mike Morgan

我发现使用条件逻辑构建 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
Afinas EM

您可以简单地使用条件语句 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 大小写:`if('condition') widget()'
M
MJ Montes

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

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

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

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

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

M
Mike Morgan

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

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

如何使用它
o
otto

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

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")]
a
alexpfx

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

H
Hamza Tanveer

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

 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
            )

            ),
          ) 
        ),

这是在属性中使用条件的最清楚的解释
C
CopsOnRoad

用一个按钮

bool _paused = false;

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

A
Aymen Dn

最简单的方法:

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

V
Val

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

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

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

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

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

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

祝你好运。


R
Raaj Patel

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

(condition) ? statement1 : statement2

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

举个实际例子

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

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


j
jon

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

以前的答案:

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

有趣的! 👍
A
Anish Vahora

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

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

a
alvperov

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


e
evals

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

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

请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助,质量更好,并且更有可能吸引赞成票。
S
Satheesh Insight

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

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

n
nzackoya

像这样做

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

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

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

C
Carlos Gallo

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

See the documentation here


i
i.AGUIR

有两种可能性:

如果您只使用一个小部件

解决方案=>

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

     Offstage(
       offstage: condition == false, 
       child: Text(""),
     ),

如果您使用两个或更多小部件

解决方案=>

      bool _visibility = false;
     
      isVisible?
          Widget1 
           :
          WIdget2

A
Anandh Krishnan

更好的方法

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

s
sourav pandit

在我看来,我更喜欢的最好和最简洁的方法是创建一个辅助 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')),
          ]

只有几个你可以添加更多


d
dan1st

仅当振动小部件

if(bool = true) Container(

child: ....

),

OR

if(bool = true) Container(

child: ....

) else new Container(child: lalala),