Do tej pory za każdym razem, gdy potrzebowałem użyć instrukcji warunkowej w widżecie, wykonałem następujące czynności (używając Centrum i kontenerów jako uproszczonych przykładów fikcyjnych):
new Center(
child: condition == true ? new Container() : new Container()
)
Chociaż kiedy próbowałem użyć instrukcji if / else, doprowadziłoby to do ostrzeżenia o martwym kodzie:
new Center(
child:
if(condition == true){
new Container();
}else{
new Container();
}
)
Co ciekawe, próbowałem z instrukcją switch case i daje mi to to samo ostrzeżenie i dlatego nie mogę uruchomić kodu. Czy robię coś źle, czy jest tak, że nie można używać instrukcji if / else lub switch bez trzepotania myśli, że jest martwy kod?
Odpowiedzi:
Właściwie można używać
if/else
iswitch
oraz wszelkie inne inline oświadczenie w dart / trzepotaniem przedsionków.Użyj natychmiastowej funkcji anonimowej
class StatmentExample extends StatelessWidget { Widget build(BuildContext context) { return Text((() { if(true){ return "tis true";} return "anything but true"; })()); } }
tj. zawijaj swoje instrukcje w funkcję
(() { // your code here }())
Zdecydowanie odradzałbym umieszczanie zbyt dużej logiki bezpośrednio w `` znacznikach '' interfejsu użytkownika, ale odkryłem, że wnioskowanie o typie w Dart wymaga trochę pracy, więc może być czasami przydatne w takich scenariuszach.
Użyj operatora trójargumentowego
condition ? Text("True") : null,
Użyj instrukcji If lub For lub operatorów spreadów w kolekcjach
children: [ ...manyItems, oneItem, if(canIKickIt) ...kickTheCan for (item in items) Text(item)
Użyj metody
child: getWidget() Widget getWidget() { if (x > 5) ... //more logic here and return a Widget
Przedefiniuj instrukcję przełącznika
Jako inną alternatywę dla operatora trójargumentowego możesz utworzyć wersję funkcji instrukcji switch, na przykład w następującym poście https://stackoverflow.com/a/57390589/1058292 .
child: case2(myInput, { 1: Text("Its one"), 2: Text("Its two"), }, Text("Default"));
źródło
W Dart
if/else
iswitch
są oświadczeniami , a nie wyrażeniami. Nie zwracają wartości, więc nie można ich przekazać do parametrów konstruktora. Jeśli masz dużo logiki warunkowej w swojej metodzie budowania, dobrą praktyką jest wypróbowanie jej uproszczenia. Na przykład możesz przenieść logikę niezależną do metod i użyćif/else
instrukcji do zainicjowania zmiennych lokalnych, których możesz później użyć.Korzystanie z metody i if / else
Widget _buildChild() { if (condition) { return ... } return ... } Widget build(BuildContext context) { return new Container(child: _buildChild()); }
Korzystanie z
if/else
Widget build(BuildContext context) { Widget child; if (condition) { child = ... } else { child = ... } return new Container(child: child); }
źródło
Dla przypomnienia, Dart 2.3 dodał możliwość używania instrukcji if / else w literałach kolekcji. Odbywa się to teraz w następujący sposób:
return Column(children: <Widget>[ Text("hello"), if (condition) Text("should not render if false"), Text("world") ],);
Flutter Issue # 28181 - Inline warunkowe renderowanie na liście
źródło
AppBar -> leading:
lubchild:
W takim przypadku zalecałbym użycie operatora trójskładnikowego:
child: condition ? Container() : Center()
i staraj się unikać kodu formularza:
if (condition) return A else return B
który jest niepotrzebnie bardziej rozwlekły niż operator trójskładnikowy.
Ale jeśli potrzeba więcej logiki, możesz również:
Użyj widżetu Builder
Builder widget jest przeznaczona dla umożliwienia korzystania z zamknięciem, gdy dziecko widget jest wymagane:
Jest wygodny zawsze, gdy potrzebujesz logiki do zbudowania widgetu , pozwala uniknąć konieczności tworzenia dedykowanej funkcji.
Korzystasz z widżetu Builder jako dziecko, podajesz swoją logikę w jego
builder
metodzie:Center( child: Builder( builder: (context) { // any logic needed... final condition = _whateverLogicNeeded(); return condition ? Container(); : Center(); } ) )
Konstruktor zapewnia wygodne miejsce do przechowywania logiki kreacji. Jest to prostsze niż bezpośrednia funkcja anonimowa proponowana przez atreeon.
Zgadzam się również, że logika powinna zostać wyodrębniona z kodu UI, ale kiedy jest to naprawdę logika UI, czasami jest bardziej czytelne, aby ją tam zachować.
źródło
Dowiedziałem się, że łatwym sposobem użycia logiki warunkowej do zbudowania interfejsu użytkownika Fluttera jest utrzymanie logiki poza interfejsem użytkownika. Oto funkcja zwracająca dwa różne kolory:
Color getColor(int selector) { if (selector % 2 == 0) { return Colors.blue; } else { return Colors.blueGrey; } }
Funkcja jest używana poniżej, aby ustawić tło 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), ], ); }, );
Bardzo fajne, ponieważ możesz ponownie użyć funkcji selektora kolorów w kilku widżetach.
źródło
Osobiście używam instrukcji if / else u dzieci z tego rodzaju instrukcją blokową. Obsługuje tylko w wersji Dart 2.3.0 powyżej.
Jeśli inaczej
Column( children: [ if (_selectedIndex == 0) ...[ DayScreen(), ] else ...[ StatsScreen(), ], ], ),
if / else if
Column( children: [ if (_selectedIndex == 0) ...[ DayScreen(), ] else if(_selectedIndex == 1)...[ StatsScreen(), ], ], ),
źródło
Możesz po prostu użyć instrukcji warunkowej
a==b?c:d
Na przykład :
Container( color: Colors.white, child: ('condition') ? Widget1(...) : Widget2(...) )
Mam nadzieję, że wpadłeś na pomysł.
Załóżmy, że jeśli nie ma innego warunku, możesz użyć SizedBox.shrink ()
Container( color: Colors.white, child: ('condition') ? Widget1(...) : SizedBox.shrink() )
Jeśli jest to kolumna, nie trzeba pisać
?:
operatoraColumn( children: <Widget>[ if('condition') Widget1(...), ], )
źródło
Oto rozwiązanie. Naprawiłem to. Oto kod
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"); } }
źródło
jeśli używasz listy widżetów, możesz użyć tego:
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(), )), ); } }
źródło
Inna alternatywa: w przypadku
switch's
podobnych stwierdzeń, z wieloma warunkami, lubię używać map: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), };
Łatwiej jest dodawać / usuwać elementy do listy warunków bez dotykania instrukcji warunkowej.
Inny przykład:
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]; } }
źródło
Lol po miesiącach używania?: Po prostu dowiaduję się, że mogę tego użyć:
Column( children: [ if (true) Text('true') else Text('false'), ], )
źródło
To świetny artykuł i rozmowa. Próbowałem użyć operatora trójskładnikowego zgodnie z opisem. Ale kod nie działał, powodując błąd, jak wspomniano.
Column(children: [ condition? Text("True"): null,],);
Powyższy trójskładnikowy przykład nie prowadzi. Dart odpowie błędem, że zamiast widżetu zwrócono wartość null. Nie możesz zwrócić wartości null. Poprawnym sposobem będzie zwrócenie widżetu:
Column(children: [ condition? Text("True"): Text("false"),],);
Aby trójka działała, musisz zwrócić Widget. Jeśli nie chcesz nic zwracać, możesz zwrócić pusty pojemnik.
Column(children: [ condition? Text("True"): Container(),],);
Powodzenia.
źródło
Z guzikiem
bool _paused = false; CupertinoButton( child: _paused ? Text('Play') : Text('Pause'), color: Colors.blue, onPressed: () { setState(() { _paused = !_paused; }); }, ),
źródło
**** Możesz także użyć warunków, używając tej metody ** **
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 ) ), ) ),
źródło
W flutter, jeśli chcesz wykonać renderowanie warunkowe, możesz zrobić to:
Column( children: <Widget>[ if (isCondition == true) Text('The condition is true'), ], );
Ale co, jeśli chcesz użyć trzeciorzędnego warunku (jeśli-jeszcze)? gdy widget podrzędny jest wielowarstwowy.
Możesz użyć tego do rozwiązania flutter_conditional_rendering pakietu flutter, który ulepsza renderowanie warunkowe, obsługuje warunki if-else i switch.
Warunek Jeśli-Inaczej:
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!'), ), ], );
Stan przełącznika:
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!'), ), ], );
Jeśli chcesz warunkowo wyrenderować listę widżetów
(List<Widget>)
zamiast jednego. UżyjConditional.list()
iConditionalSwitch.list()!
źródło
W mojej aplikacji utworzyłem
WidgetChooser
widżet, dzięki czemu mogę wybierać między widżetami bez logiki warunkowej:WidgetChooser( condition: true, trueChild: Text('This widget appears if the condition is true.'), falseChild: Text('This widget appears if the condition is false.'), );
To jest źródło
WidgetChooser
widgetu: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; } } }
źródło
Możesz użyć operatora trójargumentowego dla instrukcji warunkowych w dart, jego użycie jest proste
jeśli
condition
jest prawdziwe, tostatement1
zostanie wykonane w przeciwnym raziestatement2
.Biorąc praktyczny przykład
Pamiętaj, jeśli zamierzasz używać,
null
ponieważWidget2
lepiej jest używać,SizedBox.shrink()
ponieważ niektóre widżety nadrzędne będą zgłaszać wyjątek po uzyskaniunull
dziecka.źródło
Tylko jeśli wibruje widget
if(bool = true) Container( child: .... ), OR if(bool = true) Container( child: .... ) else new Container(child: lalala),
źródło