Как использовать условный оператор в дочернем атрибуте виджета Flutter (Center Widget)

До сих пор всякий раз, когда мне нужно было использовать условный оператор внутри виджета, я сделал следующее (использование 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();
    }
)

Интересно, что я попытался с помощью оператора case switch, и он дает мне такое же предупреждение, и поэтому я не могу запустить код. Я делаю что-то неправильно или это так, что нельзя использовать if/else или инструкции switch без трепета, думая, что есть мертвый код?

Ответ 1

В Dart if/else и switch есть выражения, а не выражения. Они не возвращают значение, поэтому вы не можете передать их параметрам конструктора. Если в вашем методе сборки есть много условной логики, то это хорошая практика, чтобы попытаться ее упростить. Например, вы можете перемещать автономную логику в методы и использовать операторы 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);
}

Ответ 2

На самом деле вы можете использовать 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
}())

Я бы настоятельно рекомендовал не помещать слишком много логики непосредственно в разметку вашего пользовательского интерфейса, но я обнаружил, что вывод типов в 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, например, в следующем посте fooobar.com/questions/18291800/....

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

Ответ 3

Я обнаружил, что простой способ использования условной логики для создания пользовательского интерфейса Flutter - это сохранить логику вне пользовательского интерфейса. Вот функция, которая возвращает два разных цвета:

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

Очень удобно, так как вы можете повторно использовать функцию выбора цвета в нескольких виджетах.

Ответ 4

Вот решение. Я исправил это. Вот код

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

Ответ 5

если вы используете список виджетов, вы можете использовать это:

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

Ответ 6

Другая альтернатива: для операторов типа 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];
  }
}

Ответ 7

У меня есть проблема, связанная с оператором if в dart, я хочу, чтобы пользователь коснулся города, чтобы перейти на новый экран. этот код работает отлично


class citySec extends StatelessWidget {
  Widget getListView(BuildContext context) {
    var listView = ListView(
      children: <Widget>[
        Text(
          "choose ur city:",
          textDirection: TextDirection.rtl,
          textAlign: TextAlign.center,
        ),
        ListTile(
          leading: Icon(Icons.location_city),
          title: Text("Toronto ", textDirection: TextDirection.rtl),

          onTap: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => TorontoUniversitySection(),
              ),
            );
          },
        ),
      ],
    );
    return listView;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(body: getListView(context));
  }
}

Тем не менее, у меня есть длинный список городов, и предыдущий код сделает мой код очень длинным, поэтому мне пришлось изменить код, и я столкнулся с некоторыми ошибками в операторах if, вот что я сделал до сих пор.


import 'package:flutter/material.dart';
import 'package:rate/screens/firstScreen.dart';

void main() {
  runApp(MaterialApp(
    debugShowCheckedModeBanner: false,
    title: 'Rate',
    home: Scaffold(
      appBar: AppBar(
        title: Text("jgfnjfnj ", textDirection: TextDirection.rtl),
      ),
      body: ListDisplay(),
    ),
  ));
}
class ListDisplay extends StatelessWidget {
  List<String> litems = ["Toronto","NewYork","London","Riyadh","Dubai","Istanbul"];

  @override
  Widget build (BuildContext ctxt) {
    return new Scaffold(
      appBar: AppBar(title: Text("Please Choose your city: ", textDirection: TextDirection.ltr,),
      ),

    body: new ListView.builder
    (
    itemCount: litems.length,

    itemBuilder: (BuildContext ctxt, int index) {

    return new ListTile(
      leading: Icon(Icons.location_city),
      title: Text(litems[index], textDirection: TextDirection.rtl),

      onTap: () {

        if (litems.contains("Totonto")){
          Navigator.push(
            ctxt,
            MaterialPageRoute(

              builder: (ctxt) => TorontoUniversitySection()
            ),
          );

        }
        else if (litems.contains("London")){
          Navigator.push(
            ctxt,
            MaterialPageRoute(

                builder: (ctxt) => LondonUniversitySection()
            ),
          );

        }


      },
    );

    }
    )
    );
  }
}

Ответ 8

**** Вы также можете использовать условия, используя этот метод ** **

 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
            )

            ),
          ) 
        ),