How to use conditional statement within child attribute of a Flutter Widget (Center Widget)

FlutterIf StatementDartConditional Statements

Flutter Problem Overview


So far whenever I needed to use a conditional statement within a Widget I have done the following (Using Center and Containers as simplified dummy examples):

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

Though when I tried using an if/else statement it would lead to an Dead code warning:

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

Interestingly enough I tried with a switch case statement and it gives me the same warning and thus I cannot run the code. Am I doing something wrong or is it so that one cannot use if/else or switch statements without flutter thinking there is dead code?

Flutter Solutions


Solution 1 - Flutter

Actually you can use if/else and switch and any other statement inline in dart / flutter.

Use an immediate anonymous function
class StatmentExample extends StatelessWidget {
  Widget build(BuildContext context) {
    return Text((() {
      if(true){
        return "tis true";}

      return "anything but true";
    })());
  }
}

ie wrap your statements in a function

(() {
  // your code here
}())

I would heavily recommend against putting too much logic directly with your UI 'markup' but I found that type inference in Dart needs a little bit of work so it can be sometimes useful in scenarios like that.

Use the ternary operator
condition ? Text("True") : null,
Use If or For statements or spread operators in collections
children: [
  ...manyItems,
  oneItem,
  if(canIKickIt)
    ...kickTheCan
  for (item in items)
    Text(item)
Use a method
child: getWidget()

Widget getWidget() {
  if (x > 5) ...
  //more logic here and return a Widget
Redefine switch statement

As another alternative to the ternary operator, you could create a function version of the switch statement such as in the following post https://stackoverflow.com/a/57390589/1058292.

  child: case2(myInput,
  {
    1: Text("Its one"),
    2: Text("Its two"),
  }, Text("Default"));

Solution 2 - Flutter

I personally use if/else statement in children with this kind of block statement. It only supports on Dart version 2.3.0 above.

if / else

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

if / else if

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

multiple widgets example

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

Solution 3 - Flutter

In Dart, if/else and switch are statements not expressions. They don't return a value so you can't pass them to constructor params. If you have a lot of conditional logic in your build method, then it is a good practice to try and simplify it. For example, you can move self-contained logic to methods, and use if/else statements to initialize local variables which you can later use.

Using a method and if/else
Widget _buildChild() {
  if (condition) {
    return ...
  }
  return ...
}

Widget build(BuildContext context) {
  return new Container(child: _buildChild());
}

###Using an if/else

Widget build(BuildContext context) {
  Widget child;
  if (condition) {
    child = ...
  } else {
    child = ...
  }
  return new Container(child: child);
}

Solution 4 - Flutter

In such a case I would recommand using the ternary operator:

child: condition ? Container() : Center()

and try to avoid code of the form:

if (condition) return A else return B

which is needlessly more verbose than the ternary operator.

But if more logic is needed you may also:

Use the Builder widget

The Builder widget is meant for allowing the use of a closure when a child widget is required:

> A platonic widget that calls a closure to obtain its child widget.

It is convenient anytime you need logic to build a widget, it avoids the need to create a dedicated function.

You use the Builder widget as the child, you provide your logic in its builder method:

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

The Builder provides a convenient place to hold the creational logic. It is more straightforward than the immediate anonymous function proposed by atreeon.

Also I agree that the logic should be extracted from the UI code, but when it's really UI logic it is sometimes more legible to keep it there.

Solution 5 - Flutter

For the record, Dart 2.3 added the ability to use if/else statements in Collection literals. This is now done the following way:

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

Flutter Issue #28181 - Inline conditional rendering in list

Solution 6 - Flutter

I found out that an easy way to use conditional logic to build Flutter UI is to keep the logic outside of the UI. Here is a function to return two different colors:

Color getColor(int selector) {
  if (selector % 2 == 0) {
    return Colors.blue;
  } else {
    return Colors.blueGrey;
  }
}

The function is used below to to set the background of the 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),
      ],
    );
  },
);

Very neat as you can reuse your color selector function in several widgets.

Solution 7 - Flutter

You can simply use a conditional statement a==b?c:d

For example :

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

I hope you got the idea.

Suppose if there is no else condition you can use a SizedBox.shrink()

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

If it is a column no need to write ?: operator

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

Solution 8 - Flutter

Aside from the ternary operator, you can also use Builder widget if you have operation needs to be performed before the condition statement.

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

Solution 9 - Flutter

Lol after months of using ?: I just find out that I can use this:

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

Solution 10 - Flutter

Here is the solution. I have fixed it. Here is the code

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

Solution 11 - Flutter

if you use a list of widgets you can use this:

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

Solution 12 - Flutter

Another alternative: for 'switch's' like statements, with a lot of conditions, I like to use maps:

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

It's easier to add/remove elements to the condition list without touch the conditional statement.

Another example:

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];
  }
}

Solution 13 - Flutter

**You can also use conditions by using this method **

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

Solution 14 - Flutter

With a button

bool _paused = false;

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

Solution 15 - Flutter

This is great article and conversation. I tried to use the ternary operator as described. But the code didn't work resulting in an error as mentioned.

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

The ternary example above is miss leading. Dart will respond with an error that a null was returned instead of widget. You can't return null. The correct way will be to return a widget:

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

In order for the ternary to work you need to return a Widget. If you don't want to return anything you can return a empty container.

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

Good luck.

Solution 16 - Flutter

EDIT: I no longer recommend the solution I posted below because I realized that using this method, both the child for the true result and the child for the false result are built but only one is used, which unnecessarily slows the code.


PREVIOUS ANSWER:

In my app I created a WidgetChooser widget so I can choose between widgets without conditional logic:

WidgetChooser(
      condition: true,
      trueChild: Text('This widget appears if the condition is true.'),
      falseChild: Text('This widget appears if the condition is false.'),
    );

This is the source for the WidgetChooser widget:

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

Solution 17 - Flutter

You can use ternary operator for conditional statements in dart, It's use is simple

(condition) ? statement1 : statement2

if the condition is true then the statement1 will be executed otherwise statement2.

Taking a practical example

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

Remember if you are going to use null as Widget2 it is better to use SizedBox.shrink() because some parent widgets will throw an exception after getting a null child.

Solution 18 - Flutter

You can use builder in following manning: I have consider a condition where we can get image url as null, hence if null I show a shrink sizedbox as it has no property a completely void widget.

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

Solution 19 - Flutter

The simplest way:

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

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

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

If you want to render MULTIPLE WIDGETS for one condition, you can use the spread operator:

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

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

Solution 20 - Flutter

Conditional rendering in Flutter can easily be done by proviso package. It has a comprehensive set of conditional widgets and builders to make a more readable and simpler conditional statement code.

The API & helpers consist of but not limited to:

conditional widgets & builders:

ConditionWidget(
  condition: starred,
  widget: Icon(
    Icons.favorite
  ),
  fallback: fallbackWidget
)

ConditionBuilder(
  condition: (_) => someCondition,
  trueBuilder: (_) => trueWidget,
  fallbackBuilder: (_) => fallbackWidget
)

switch case conditions:

SwitchCaseBuilder.widget<String>(
  context: context,
  condition: (_) => '1',
  caseBuilders: {'1': (_) => someWidget(), '2': (_) => someWidget()},
  fallbackBuilder: (_) => fallbackWidget,
);  

or even a conditional parent widget

ConditionalWrap(
  shouldWrap: shouldWrapChildInParent,
  child: Container(),
  parentBuilder: (child) => Container(
    child: child,
  ),
)

API supports either a single or multiple widgets rendering. You are welcome to give it a try.

Solution 21 - Flutter

I prefer using Map

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

and inside the build function i pass the key to the map like this

new Center(
 child: pageSelector["here pass the key"] ?? Text("some default widget"),
)

or another solution is to use simple function

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

and inside the build function pass the number of widget or any other parameter to check

new Center(
 child: conditionalWidget(pageNumber),
)

Solution 22 - Flutter

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

Solution 23 - Flutter

I have no idea whether it's a good practice, but I am using:

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

Solution 24 - Flutter

Do it like this

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

So when you want to show something with condition you do like say

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

Solution 25 - Flutter

If you want to avoid using if statements, you can use the Flutter Visibility widget

See the documentation here

Solution 26 - Flutter

There are two possibilities :

  1. if you are using one widget only

Solution=>

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

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

2. if you are using two widgets or more

Solution=>

      bool _visibility = false;
     
      isVisible?
          Widget1 
           :
          WIdget2

Solution 27 - Flutter

> A better way

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

Solution 28 - Flutter

Only if vibrating widget

if(bool = true) Container(

child: ....

),

OR

if(bool = true) Container(

child: ....

) else new Container(child: lalala),

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMarkoView Question on Stackoverflow
Solution 1 - FlutteratreeonView Answer on Stackoverflow
Solution 2 - FlutterbrendanView Answer on Stackoverflow
Solution 3 - FlutterJonah WilliamsView Answer on Stackoverflow
Solution 4 - Fluttermr_mmmmoreView Answer on Stackoverflow
Solution 5 - FlutterHaojenView Answer on Stackoverflow
Solution 6 - FlutterWillie NandiView Answer on Stackoverflow
Solution 7 - FlutterAfinas EMView Answer on Stackoverflow
Solution 8 - FlutterMJ MontesView Answer on Stackoverflow
Solution 9 - FlutterLudmilKirovView Answer on Stackoverflow
Solution 10 - FlutterYasir MalikView Answer on Stackoverflow
Solution 11 - FlutterottoView Answer on Stackoverflow
Solution 12 - FlutteralexpfxView Answer on Stackoverflow
Solution 13 - FlutterHamza TanveerView Answer on Stackoverflow
Solution 14 - FlutterRio WeberView Answer on Stackoverflow
Solution 15 - FlutterValView Answer on Stackoverflow
Solution 16 - FlutterjonView Answer on Stackoverflow
Solution 17 - FlutterRaaj PatelView Answer on Stackoverflow
Solution 18 - FlutterAnish VahoraView Answer on Stackoverflow
Solution 19 - FlutterAymen DnView Answer on Stackoverflow
Solution 20 - FlutteralvperovView Answer on Stackoverflow
Solution 21 - FlutterevalsView Answer on Stackoverflow
Solution 22 - FlutterRahul RajView Answer on Stackoverflow
Solution 23 - FlutterSatheesh InsightView Answer on Stackoverflow
Solution 24 - FlutternzackoyaView Answer on Stackoverflow
Solution 25 - FlutterCarlos GalloView Answer on Stackoverflow
Solution 26 - Flutteri.AGUIRView Answer on Stackoverflow
Solution 27 - FlutterAnandh KrishnanView Answer on Stackoverflow
Solution 28 - FlutterRenato SantosView Answer on Stackoverflow