วิธีใช้คำสั่งเงื่อนไขภายในแอตทริบิวต์ลูกของ Flutter Widget (Center Widget)


130

เมื่อใดก็ตามที่ฉันต้องการใช้คำสั่งเงื่อนไขภายในวิดเจ็ตฉันได้ทำสิ่งต่อไปนี้แล้ว (ใช้ Center และ Containers เป็นตัวอย่างจำลองที่เรียบง่าย):

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

แม้ว่าเมื่อฉันลองใช้คำสั่ง if / else มันจะนำไปสู่คำเตือน Dead code:

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

น่าสนใจพอที่ฉันลองใช้คำสั่ง switch case และมันก็ให้คำเตือนแบบเดียวกันกับฉันดังนั้นฉันจึงไม่สามารถเรียกใช้รหัสได้ ฉันทำอะไรผิดพลาดหรือเปล่าหรือเป็นสิ่งที่ไม่สามารถใช้ if / else หรือเปลี่ยนคำสั่งได้โดยไม่คิดว่ามีรหัสตาย


1
หากคุณต้องการแทรกบล็อกที่ควรสร้างอินสแตนซ์วิดเจ็ตคุณน่าจะสร้างวิดเจ็ตในเมธอดคลาสได้ดีกว่า
aziza

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

คำตอบ:


157

จริงๆแล้วคุณสามารถใช้if/elseและswitchและคำสั่งอื่น ๆ แบบอินไลน์ในโผ / กระพือ

ใช้ฟังก์ชันนิรนามทันที

class StatmentExample extends StatelessWidget {
  Widget build(BuildContext context) {
    return Text((() {
      if(true){
        return "tis true";}

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

เช่นห่องบของคุณในฟังก์ชัน

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

ฉันขอแนะนำอย่างยิ่งว่าอย่าใส่ตรรกะมากเกินไปโดยตรงกับ 'มาร์กอัป' UI ของคุณ แต่ฉันพบว่าการอนุมานประเภทใน Dart ต้องการการทำงานเล็กน้อยดังนั้นบางครั้งจึงมีประโยชน์ในสถานการณ์เช่นนั้น

ใช้ตัวดำเนินการ ternary

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

กำหนดคำสั่งสวิตช์ใหม่

ในฐานะที่เป็นอีกทางเลือกหนึ่งให้กับผู้ประกอบการ ternary คุณสามารถสร้างรุ่นที่ฟังก์ชั่นของคำสั่งสวิทช์ดังกล่าวในการโพสต์ต่อไปนี้เป็น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" คำสั่งเงื่อนไขของคุณอาจไม่ได้รับการประเมินใหม่จนกว่าการดำเนินการอื่น ๆ จะสร้างวิดเจ็ตของคุณขึ้นมาใหม่ . คุณต้องได้รับตัวแปรเงื่อนไขของคุณผ่านทาง "ผู้บริโภค" ที่กำลังถูกส่งกลับไปยังฟังก์ชันการสร้างวิดเจ็ตจากนั้นคำสั่งเงื่อนไขของคุณควรได้รับการประเมินอย่างเหมาะสมอีกครั้งเมื่อมีการเปลี่ยนแปลงสถานะทั่วโลก
Matthew Rideout

หนึ่งในสิ่งที่ดีที่สุดสำหรับแนวทางปฏิบัติที่ดีในการโผ / กระพือ
Kohls

72

ใน Dart if/elseและswitchเป็นคำสั่งไม่ใช่นิพจน์ พวกเขาไม่ส่งคืนค่าดังนั้นคุณจึงไม่สามารถส่งต่อไปยังพารามิเตอร์ตัวสร้างได้ หากคุณมีตรรกะเงื่อนไขจำนวนมากในวิธีการสร้างของคุณก็เป็นแนวทางปฏิบัติที่ดีที่จะพยายามทำให้ง่ายขึ้น ตัวอย่างเช่นคุณสามารถย้ายตรรกะที่มีอยู่ในตัวไปยังวิธีการและใช้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

35

สำหรับเรกคอร์ด Dart 2.3 ได้เพิ่มความสามารถในการใช้คำสั่ง if / else ใน Collection literals ตอนนี้ทำได้ด้วยวิธีต่อไปนี้:

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

Flutter Issue # 28181 - การแสดงผลตามเงื่อนไขแบบอินไลน์ในรายการ


ฉันมีโผ 2.5 แต่พบข้อผิดพลาดในการเรียกใช้โค้ดด้านบน มันระบุว่ารหัสนี้จำเป็นเพื่อให้เข้ากันได้กับเวอร์ชันก่อนหน้านี้ ลองอัปเดตข้อ จำกัด
Aseem

น่าสนใจ ~
Haojen

พวกเขาเพิ่มคุณสมบัติลูปหรือไม่? ถ้าเป็นเช่นนั้นจะใช้งานได้อย่างไร?
princebillyGK


ใช้ไม่ได้กับวิดเจ็ตเดียวเช่นAppBar -> leading:หรือchild:
Alex Vang

33

ในกรณีนี้ฉันขอแนะนำให้ใช้ตัวดำเนินการ ternary:

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 จริงๆบางครั้งก็ชัดเจนกว่าที่จะเก็บไว้ที่นั่น


สิ่งนี้ใช้ได้ผลสำหรับฉันสำหรับรายการลิ้นชักคลิกและอัปเดตร่างกาย
เรียนรู้อย่างรวดเร็ว

23

ฉันพบว่าวิธีง่ายๆในการใช้ตรรกะเงื่อนไขเพื่อสร้าง 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),
      ],
    );
  },
);

เรียบร้อยมากเนื่องจากคุณสามารถใช้ฟังก์ชันตัวเลือกสีของคุณซ้ำในวิดเจ็ตต่างๆได้


2
ฉันลองสิ่งนี้และได้ผลสำหรับฉันในแบบที่แน่นอน ขอบคุณ
Ajay Kumar

18

โดยส่วนตัวฉันใช้คำสั่ง if / else ในเด็กด้วยคำสั่งบล็อกประเภทนี้ รองรับเฉพาะ Dart เวอร์ชัน 2.3.0 ข้างต้นเท่านั้น

ถ้า / else

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

ถ้า / 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
ถ้าไม่มีเงื่อนไขอื่นล่ะ? ในคอลัมน์การพูดว่า a == b? c: null จะไม่ทำงาน
cwhisperer

1
คุณสามารถใช้ SizedBox.shrick () เป็นวิดเจ็ตที่สองได้ อัปเดตคำตอบ
Afinas EM

1
หากเป็นคอลัมน์คุณสามารถใช้ if condition ได้โดยตรงโดยไม่มีกรณีอื่น: วิดเจ็ต if ('condition') () '
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(),
      )),
    );
  }
}

เงื่อนไข? ข้อความ ("True"): null ซึ่งทำให้เกิดข้อผิดพลาด Asertion false ในคอนโซลในการดำเนินการรันไทม์
exequielc

@exequielc คุณต้องเพิ่ม. where (notNull) .toList () และจุดสิ้นสุดของ WidgetList และวิธีการบูล notNull (Object o) => o! = null; ลองดูตัวอย่างทั้งหมด ...
Tobias

1
ตั้งแต่ Dart 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];
  }
}


2

นี่เป็นบทความและบทสนทนาที่ยอดเยี่ยม ฉันพยายามใช้ตัวดำเนินการ ternary ตามที่อธิบายไว้ แต่รหัสไม่ทำงานส่งผลให้เกิดข้อผิดพลาดตามที่กล่าวไว้

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

ตัวอย่างด้านบนไม่ได้นำหน้า Dart จะตอบกลับด้วยข้อผิดพลาดที่ส่งคืนค่าว่างแทนวิดเจ็ต คุณไม่สามารถคืนค่าว่างได้ วิธีที่ถูกต้องคือการส่งคืนวิดเจ็ต:

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

เพื่อให้ ternary ทำงานได้คุณต้องส่งคืน Widget หากคุณไม่ต้องการส่งคืนสิ่งใดคุณสามารถส่งคืนคอนเทนเนอร์เปล่าได้

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

โชคดี.



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

แต่ถ้าคุณต้องการใช้เงื่อนไขระดับตติยภูมิ (if-else) ล่ะ? เมื่อวิดเจ็ตลูกมีหลายชั้น

คุณสามารถใช้สิ่งนี้สำหรับโซลูชันflutter_conditional_renderingแพ็คเกจกระพือซึ่งช่วยเพิ่มการแสดงผลตามเงื่อนไขรองรับ 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>)แทนที่จะเป็นวิดเจ็ตเดียว ใช้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

คุณสามารถใช้ตัวดำเนินการ ternary สำหรับประโยคเงื่อนไขในโผการใช้งานนั้นง่ายมาก

(condition) ? statement1 : statement2

ถ้าconditionเป็นจริงแล้วจะถูกดำเนินการอย่างอื่นstatement1statement2

เป็นตัวอย่างที่ใช้ได้จริง

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.