Cách sử dụng câu lệnh điều kiện trong thuộc tính con của Tiện ích con Flutter (Tiện ích con ở giữa)


117

Cho đến nay bất cứ khi nào tôi cần sử dụng một câu lệnh điều kiện trong một Widget, tôi đã làm như sau (Sử dụng Trung tâm và Vùng chứa làm ví dụ giả đơn giản hóa):

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

Mặc dù khi tôi thử sử dụng câu lệnh if / else, nó sẽ dẫn đến cảnh báo Mã chết:

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

Điều thú vị là tôi đã thử với một câu lệnh trường hợp chuyển đổi và nó đưa ra cảnh báo tương tự và do đó tôi không thể chạy mã. Có phải tôi đang làm sai điều gì đó hay là nó khiến người ta không thể sử dụng if / else hoặc chuyển đổi các câu lệnh mà không lo lắng vì nghĩ rằng có mã chết?


1
Nếu bạn muốn chèn một khối nơi widget nên được instantiated bạn có lẽ tốt hơn xây dựng widget bằng phương pháp lớp
Aziza

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

Câu trả lời:


132

Trên thực tế, bạn có thể sử dụng if/elseswitchvà bất kỳ câu lệnh nội dòng nào khác trong dart / Flaming.

Sử dụng một chức năng ẩn danh ngay lập tức

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

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

tức là gói các câu lệnh của bạn trong một hàm

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

Tôi thực sự khuyên bạn không nên đặt quá nhiều logic trực tiếp với 'đánh dấu' giao diện người dùng của bạn nhưng tôi thấy rằng kiểu suy luận trong Dart cần một chút công việc nên đôi khi nó có thể hữu ích trong các tình huống như vậy.

Sử dụng toán tử bậc ba

condition ? Text("True") : null,

Sử dụng câu lệnh If hoặc For hoặc toán tử trải rộng trong tập hợp

children: [
  ...manyItems,
  oneItem,
  if(canIKickIt)
    ...kickTheCan
  for (item in items)
    Text(item)

Sử dụng một phương pháp

child: getWidget()

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

Xác định lại câu lệnh chuyển đổi

Là một thay thế khác cho toán tử bậc ba, bạn có thể tạo một phiên bản hàm của câu lệnh switch, chẳng hạn như trong bài đăng sau https://stackoverflow.com/a/57390589/1058292 .

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

9
Theo tôi, đây là câu trả lời đầy đủ nhất, nhờ @orangesherbert
Oniya Daniel

2
Chỉ cần lưu ý nếu ai đó gặp khó khăn, nếu bạn đang sử dụng Nhà cung cấp để xây dựng lại tiện ích con của mình khi thay đổi trạng thái toàn cầu và bạn đang nhận dữ liệu qua "Provider.of", thì câu lệnh điều kiện của bạn có thể không được đánh giá lại cho đến khi một số hành động khác xây dựng lại tiện ích con của bạn . Bạn cần nhận được biến có điều kiện của mình thông qua "Người tiêu dùng" đang được trả về chức năng xây dựng Tiện ích, sau đó câu lệnh điều kiện của bạn sẽ được đánh giá lại đúng khi các thay đổi trạng thái toàn cục.
Matthew Rideout

Một trong những điều tốt nhất để thực hành tốt trong phi tiêu / bay
Kohls

72

Trong Dart, if/elseswitchlà các câu lệnh không phải là biểu thức. Chúng không trả về một giá trị nên bạn không thể chuyển chúng đến các tham số của hàm tạo. Nếu bạn có nhiều logic điều kiện trong phương thức xây dựng của mình, thì bạn nên thử và đơn giản hóa nó. Ví dụ, bạn có thể di chuyển logic độc lập sang các phương thức và sử dụng các if/elsecâu lệnh để khởi tạo các biến cục bộ mà bạn có thể sử dụng sau này.

Sử dụng một phương thức và if / else

Widget _buildChild() {
  if (condition) {
    return ...
  }
  return ...
}

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

Sử dụng một if/else

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

1
Đây phải là câu trả lời chính xác! Cảm ơn bạn đã làm rõ điều này nó đã giúp tôi!
Slamit

31

Đối với bản ghi, Dart 2.3 đã thêm khả năng sử dụng các câu lệnh if / else trong các ký tự Collection. Điều này hiện được thực hiện theo cách sau:

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

Flutter Issue # 28181 - Hiển thị có điều kiện nội tuyến trong danh sách


Tôi có phi tiêu 2.5 nhưng tôi gặp lỗi khi chạy mã trên. Nó nói rằng mã này được yêu cầu để tương thích với các phiên bản trước đó. thử cập nhật các ràng buộc SDK '
Aseem

emmm, thú vị ~
Haojen

Họ có thêm tính năng vòng lặp for không? nếu vậy làm thế nào để thực hiện nó?
PrincebillyGK


Không hoạt động với một tiện ích như AppBar -> leading:hoặcchild:
Alex Vang

26

Các câu trả lời khác không đề cập đến nó, bạn cũng có thể:

Sử dụng tiện ích Builder

Các Builder Widget có nghĩa là cho phép việc sử dụng một kết thúc khi một đứa trẻ phụ tùng được yêu cầu:

Một widget platonic gọi một lệnh đóng để lấy widget con của nó.

Thật tiện lợi bất cứ khi nào bạn cần logic để xây dựng một widget , nó tránh được việc phải tạo một chức năng chuyên dụng. Ngoài ra, tôi thấy nó làm cho những gì đang được thực hiện rõ ràng hơn so với việc sử dụng một chức năng ẩn danh ngay lập tức.

Bạn sử dụng tiện ích con Builder và cung cấp logic của bạn trong builderphương pháp của nó . Với ví dụ của bạn, nó đi:

Center(
  child: Builder(
    builder: (context) {
      if (condition) {
        return Container();
      } else {
        return Center();
      }
    }
  )
)

Trong một ví dụ đơn giản như vậy, toán tử bậc ba sẽ đủ ( child: condition ? Container() : Center()), nhưng nếu cần thêm logic, Bộ dựng cung cấp một nơi thuận tiện để giữ nó.

Ngoài ra, tôi đồng ý với các áp phích khác rằng logic nên được trích xuất từ ​​mã giao diện người dùng, nhưng khi nó chỉ là một switchhoặc if/ elsecâu lệnh được sử dụng để xác định tiện ích con cần xây dựng, tôi muốn giữ nó ở đó (miễn là điều kiện đơn giản, ví dụ kiểm tra một trong một ViewModel). Tiện ích Builder có thể giúp bạn trong việc này.


điều này làm việc khá tốt cho tôi đối với các mục trong ngăn kéo và cập nhật nội dung
học nhanh

22

Tôi phát hiện ra rằng một cách dễ dàng để sử dụng logic có điều kiện để xây dựng giao diện người dùng Flutter là giữ logic bên ngoài giao diện người dùng. Đây là một hàm để trả về hai màu khác nhau:

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

Hàm được sử dụng bên dưới để thiết lập nền của 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),
      ],
    );
  },
);

Rất gọn gàng vì bạn có thể sử dụng lại chức năng chọn màu của mình trong một số widget.


1
Tôi đã thử điều này và làm việc cho tôi theo cách chính xác. Cảm ơn
Ajay Kumar

17

Bạn chỉ có thể sử dụng một câu lệnh điều kiện a==b?c:d

Ví dụ :

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

Tôi hy vọng bạn có ý tưởng.

Giả sử nếu không có điều kiện nào khác, bạn có thể sử dụng SizedBox.shrink ()

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

Nếu nó là một cột không cần viết ?:toán tử

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

1
Nếu không có điều kiện nào khác thì sao? Trong Cột, nói a == b? C: null sẽ không hoạt động
cwhisperer

1
Bạn chỉ cần sử dụng SizedBox.shrick () làm tiện ích con thứ hai. đang cập nhật câu trả lời.
Afinas EM

1
Nếu đó là một cột thì bạn có thể sử dụng if điều kiện trực tiếp mà không có trường hợp khác: `` if ('condition') widget () '
Afinas EM

16

Cá nhân tôi sử dụng câu lệnh if / else ở trẻ em với loại câu lệnh khối này. Nó chỉ hỗ trợ trên phiên bản Dart 2.3.0 ở trên.

nếu khác

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

nếu / khác nếu

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

1
Cái này đẹp và chắc chắn. Cảm ơn.
jacvalle

10

Đây là giải pháp. Tôi đã sưa nó. Đây là mã

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

Làm thế nào để sử dụng nó
ardi

6

nếu bạn sử dụng một danh sách các widget, bạn có thể sử dụng cái này:

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

tình trạng? Văn bản ( "True"): null, điều này không một lỗi Asertion sai trong giao diện điều khiển, trên thực runtime
exequielc

@exequielc bạn phải thêm .where (notNull) .toList () và phần cuối của WidgetList và phương thức bool notNull (Object o) => o! = null ;. Hãy thử toàn bộ ví dụ ...
wwwwwwwwwwww

1
Tính đến Dart 2.3 có điều kiện bao gồm một widget trong một danh sách, bạn có thể sử dụng: [Text ( "Hello"), if (thế giới) Text ( "World")]
Brett Sutton

4

Một thay thế khác: đối với các switch'scâu lệnh như '', với rất nhiều điều kiện, tôi thích sử dụng bản đồ:

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

Việc thêm / xóa các phần tử vào danh sách điều kiện dễ dàng hơn mà không cần chạm vào câu lệnh điều kiện.

Một vi dụ khac:

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

Ví dụ thực hành:

Với một nút

bool _paused = false;

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

1

**** Bạn cũng có thể sử dụng các điều kiện bằng cách sử dụng phương pháp này ** **

 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

Đây là một bài báo và cuộc trò chuyện tuyệt vời. Tôi đã cố gắng sử dụng toán tử bậc ba như được mô tả. Nhưng mã không hoạt động dẫn đến lỗi như đã đề cập.

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

Ví dụ bậc ba ở trên là bỏ sót hàng đầu. Dart sẽ phản hồi với lỗi rằng giá trị null được trả về thay vì tiện ích con. Bạn không thể trả về null. Cách chính xác sẽ là trả về một widget:

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

Để chim nhạn hoạt động, bạn cần trả lại một Widget. Nếu bạn không muốn trả lại bất cứ thứ gì, bạn có thể trả lại một vùng chứa trống.

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

Chúc may mắn.


1

Trong nháy mắt, nếu bạn muốn kết xuất có điều kiện, bạn có thể làm như sau:

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

Nhưng nếu bạn muốn sử dụng điều kiện bậc ba (nếu-khác) thì sao? khi tiện ích con có nhiều lớp.

Bạn có thể sử dụng điều này cho giải pháp của nó flay_conditional_rendering một gói flamingo giúp tăng cường kết xuất có điều kiện, hỗ trợ if-else và điều kiện chuyển đổi.

Điều kiện 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!'),
        ),
      ],
    );

Điều kiện chuyển đổi:

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

Nếu bạn muốn hiển thị có điều kiện một danh sách các tiện ích (List<Widget>)thay vì một tiện ích duy nhất. Sử dụng Conditional.list()ConditionalSwitch.list()!


1

Lol sau nhiều tháng sử dụng ?: Tôi chỉ phát hiện ra rằng tôi có thể sử dụng cái này:

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

1

Bạn có thể sử dụng toán tử bậc ba cho các câu lệnh điều kiện trong dart, Cách sử dụng rất đơn giản

(condition) ? statement1 : statement2

nếu conditionđúng thì di statement1chúc sẽ được thực hiện ngược lại statement2.

Lấy một ví dụ thực tế

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

Hãy nhớ nếu bạn định sử dụng nullWidget2tốt hơn nên sử dụng SizedBox.shrink()vì một số widget dành cho cha mẹ sẽ ném ra một ngoại lệ sau khi có nullcon.


0

Trong ứng dụng của mình, tôi đã tạo một WidgetChooserwidget để tôi có thể chọn giữa các widget mà không cần logic có điều kiện:

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

Đây là nguồn cho WidgetChoosertiện ích:

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

-3

Chỉ khi tiện ích rung

if(bool = true) Container(

child: ....

),

OR

if(bool = true) Container(

child: ....

) else new Container(child: lalala),
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.