Flutterウィジェット(センターウィジェット)の子属性内で条件ステートメントを使用する方法


130

これまで、ウィジェット内で条件ステートメントを使用する必要があるときはいつでも、次のことを行いました(簡略化されたダミーの例として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
ウィジェットをインスタンス化する必要があるブロックを挿入する場合は、クラスメソッドでウィジェットを作成する方がよいでしょう
aziza 2018

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

回答:


156

実際に、ダーツ/フラッターでインラインでif/elseandswitchやその他のステートメントを使用できます。

即時匿名関数を使用する

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ステートメントを再定義します

三項演算子の別の代替手段として、次の投稿https://stackoverflow.com/a/57390589/1058292のようにswitchステートメントの関数バージョンを作成できます

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

9
私の意見では、これは最も完全な答えは、感謝@orangesherbert
Oniyaダニエル

2
誰かが行き詰まった場合、グローバルな状態変化でウィジェットを再構築するためにプロバイダーを使用していて、「Provider.of」を介してデータを取得している場合は、他のアクションがウィジェットを再構築するまで、条件ステートメントが再評価されない可能性があります。 。ウィジェットビルド関数に返される「コンシューマー」を介して条件変数を取得する必要があります。その後、グローバル状態の変化に応じて条件ステートメントを適切に再評価する必要があります。
マシューライドアウト

ダーツ/フラッターのグッドプラクティスのベストプラクティスの1つ
コールズ

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
これは正解です!この説明をありがとう、それは私を助けました!
スラミット

34

記録のために、Dart 2.3は、コレクションリテラルでif / elseステートメントを使用する機能を追加しました。これは現在、次の方法で行われます。

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

Flutter Issue#28181-リスト内のインライン条件付きレンダリング


dart 2.5を使用していますが、上記のコードを実行するとエラーが発生します。`このコードは以前のバージョンと互換性がある必要があります。SDKのconstraints`を更新してみてください
Aseem

emmm、おもしろい〜
Haojen19年

forループ機能を追加しますか?もしそうなら、それをどのように実装するのですか?
princebillyGK


AppBar -> leading:またはのような単一のウィジェットでは機能しませんchild:
Alex Vang 2010年

33

このような場合、三項演算子を使用することをお勧めします。

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ロジックである場合は、そこに保持する方が読みやすい場合があります。


これは、引き出しアイテムのクリックと本文の更新に非常にうまく機能しました
クイックラーナー

22

条件付きロジックを使用してFlutterUIを構築する簡単な方法は、ロジックをUIの外部に保持することであることがわかりました。2つの異なる色を返す関数は次のとおりです。

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
私はこれを試し、正確な方法で作業しました。ありがとう
AjayKumar19年

18

私は個人的に、この種のブロックステートメントを持つ子供にif / elseステートメントを使用します。上記の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(),
        ],
    ],
 ),

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と言う:nullではないでしょう仕事?
cwhisperer

1
2番目のウィジェットとしてSizedBox.shrick()を使用するだけです。答えを更新します。
AfinasEM20年

1
列の場合は、if条件をelseケースなしで直接使用できます。 `if( 'condition')widget() '
AfinasEM20年

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

状態?テキスト(「真」):ヌル、これはランタイム実行に、コンソールにエラーAsertionの虚偽を行います
exequielc

@exequielc .where(notNull).toList()とWidgetListの末尾、およびメソッドbool notNull(Object o)=> o!= null;を追加する必要があります。全体の例を試してみてください...
トビアス

1
ダート2.3のとおり条件付きで使用することができ、リスト内のウィジェットが含まします[テキスト(「こんにちは」)、(世界)テキスト(「世界」)の場合]
ブレット・サットン

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

上記の3つの例は、ミスリーディングです。Dartは、ウィジェットの代わりにnullが返されたというエラーで応答します。nullを返すことはできません。正しい方法は、ウィジェットを返すことです。

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

三元が機能するためには、ウィジェットを返す必要があります。何も返却したくない場合は、空のコンテナを返却できます。

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'),
   ],
 );

しかし、3次(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<Widget>)1つではなく、条件付きでレンダリングする場合。使用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;
    }
  }
}

共有してくれてありがとう!
ペトロ

1

dartの条件文に三項演算子を使用できます。使用は簡単です。

(condition) ? statement1 : statement2

conditiontrueの場合、はstatement1実行されますstatement2。それ以外の場合は実行されます。

実用的な例をとる

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

あなたが使用しようとしている場合は覚えているnullとしてWidget2、使用することをお勧めしますSizedBox.shrink()いくつかの親ウィジェットを取得した後に例外がスローされますので、null子供を。


-4

ウィジェットを振動させる場合のみ

if(bool = true) Container(

child: ....

),

OR

if(bool = true) Container(

child: ....

) else new Container(child: lalala),
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.