【问题标题】:flutter setState does not add a widgetflutter setState 不添加小部件
【发布时间】:2021-05-01 00:22:21
【问题描述】:

这是我的代码。当您在上面的字段中输入城市然后按加号按钮时,它应该添加一个列表图块。但事实并非如此!有一个列表视图,其中包含所有列表图块。列表视图应该显示列表中的所有列表图块。 当我按下按钮时,会打印一条消息以指示城市数量。它显示添加了城市,但屏幕上没有任何变化。 ColorfulBox 是我构建的一个小部件。这只是一个装饰品。

import 'package:flutter/material.dart';
import 'package:learner/logic/Weather.dart';
import 'ColorfulBox.dart';

class CitiesScreen extends StatefulWidget{
  @override
  _CitiesScreenState createState() => _CitiesScreenState();
}
class _CitiesScreenState extends State<CitiesScreen>{
  List<Weather> weatherData = List<Weather>();
  String cityName;
  List<Widget> cities = List<Widget>();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
        child: Column(
          children: <Widget>[
            DecoratedBox(
              decoration: BoxDecoration(color: Colors.blueAccent, borderRadius: BorderRadius.circular(10),
              gradient: LinearGradient(colors: [Colors.blue, Colors.purple]) ),
              child: ColorfulBox(Padding(
                padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0),
                child: ListTile(
                  title: TextField(onChanged: (value){
                    cityName = value;
                  },
                  style: TextStyle(fontSize: 20, color: Colors.white),),
                  trailing: FlatButton(
                    child: Icon(Icons.add, size: 30, color: Colors.white,),
                    onPressed: (){
                      setState(() {
                        addCity(cityName);
                        print(cities.length);
                      });
                    },
                  ),
                ),
              ),
              )
            ),
            SizedBox(height: 30,),
            Expanded(
              child: ListView(
                shrinkWrap: true,
                scrollDirection: Axis.vertical,
                children: cities,
              ),
            )
          ],
        ),
      ),
    );
  }

  void addCity(String city){
    weatherData.add(Weather(city: city));
    Container toBeAddedCity = Container(
      margin: const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
      child:  Text(city, style: TextStyle(fontSize: 22, color: Colors.white),),
    );
    cities.add(ColorfulBox(toBeAddedCity));
  }

}

你能帮我解决这个问题吗?我不知道! 是不是因为 addCity 方法超出了 build 方法?还是添加但不显示?

【问题讨论】:

    标签: flutter widget setstate


    【解决方案1】:

    您可以只使用ListView.builder(...) 来创建您的小部件。请不要将小部件存储为状态。

    示例:

    class CitiesScreen extends StatefulWidget {
      @override
      _CitiesScreenState createState() => _CitiesScreenState();
    }
    
    class _CitiesScreenState extends State<CitiesScreen> {
      final TextEditingController _controller = TextEditingController();
      final List<Weather> _weatherData = <Weather>[];
      final Random _rand = Random();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Padding(
            padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
            child: Column(
              children: <Widget>[
                DecoratedBox(
                  decoration: const BoxDecoration(
                    color: Colors.blueAccent,
                    borderRadius: BorderRadius.all(Radius.circular(10)),
                    gradient: LinearGradient(
                      colors: <Color>[Colors.blue, Colors.purple],
                    ),
                  ),
                  child: Container(
                    //ColorfulBox(
                    color: Colors.blue,
                    child: Padding(
                      padding: const EdgeInsets.symmetric(vertical: 10),
                      child: ListTile(
                        title: TextField(
                          controller: _controller,
                          style: const TextStyle(fontSize: 20, color: Colors.white),
                        ),
                        trailing: FlatButton(
                          child: const Icon(
                            Icons.add,
                            size: 30,
                            color: Colors.white,
                          ),
                          onPressed: () {
                            setState(() {
                              _weatherData.add(Weather(city: _controller.text));
                            });
                            _controller.clear();
                          },
                        ),
                      ),
                    ),
                  ),
                ),
                const SizedBox(height: 30),
                Expanded(
                  child: ListView.builder(
                    shrinkWrap: true,
                    itemCount: _weatherData.length,
                    itemBuilder: (_, int index) => ListTile(
                      tileColor: Color.fromARGB(
                        255,
                        _rand.nextInt(255),
                        _rand.nextInt(255),
                        _rand.nextInt(255),
                      ),
                      title: Text(
                        _weatherData[index].city,
                        style: const TextStyle(
                          fontSize: 22,
                          color: Colors.white,
                        ),
                      ),
                    ),
                  ),
                )
              ],
            ),
          ),
        );
      }
    }
    

    【讨论】:

      【解决方案2】:

      首先,获取 TextField 值的一种便捷方法是使用TextEditingController,而不是使用变量:

      // Create a controller
      final TextEditingController _textController = TextEditingController();
      
      // Then use it in your TextField 
      TextField(
         controller: _textController,
      
         // ... other lines
      
         trailing: FlatButton(
         onPressed: () {
      
           // Use the TextController's value
           setState(() {
             addCity(_textController.text);
           });
      
           // Clear the text after using it
           _textController.clear();
           },
         ),
      ),
      

      因为您只更新 cities 数组的内容,但保持与 ListView 的孩子相同的 cities 数组,Flutter 假定状态不会改变,因此不会更新 UI。有两种方法可以解决这个问题:

      1. 改变整个列表(不推荐用于大量项目):
      // Set new value to the list, instead of just adding items in
      cities = List.from(cities)..add(ColorfulBox(toBeAddedCity)); 
      
      1. 使用 ListView.builder() 跟踪列表的长度(添加/删除项目时会修改)(推荐)
      ListView.builder(
         itemCount: cities.length,
         itemBuilder: (context, index) => cities[index]
         // ... other lines
      

      工作代码:

      
      import 'package:flutter/material.dart';
      import 'package:learner/logic/Weather.dart';
      import 'ColorfulBox.dart';
      
      class CitiesScreen extends StatefulWidget {
        @override
        _CitiesScreenState createState() => _CitiesScreenState();
      }
      
      class _CitiesScreenState extends State<CitiesScreen> {
        final TextEditingController _textEditingController = TextEditingController();
        List<Weather> weatherData = List<Weather>();
        String cityName;
        List<Widget> cities = List<Widget>();
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            body: Padding(
              padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
              child: Column(
                children: <Widget>[
                  DecoratedBox(
                      decoration: BoxDecoration(color: Colors.blueAccent,
                          borderRadius: BorderRadius.circular(10),
                          gradient: LinearGradient(
                              colors: [Colors.blue, Colors.purple])),
                      child: ColorfulBox(Padding(
                        padding: const EdgeInsets.symmetric(
                            vertical: 10, horizontal: 0),
                        child: ListTile(
                          title: TextField(
                            controller: _textEditingController,
                            style: TextStyle(fontSize: 20, color: Colors.white),),
                          trailing: FlatButton(
                            child: Icon(Icons.add, size: 30, color: Colors.white,),
                            onPressed: () {
                              setState(() {
                                addCity(_textController.text);
                                _textController.clear();
                                print(cities.length);
                              });
                            },
                          ),
                        ),
                      ),
                      )
                  ),
                  SizedBox(height: 30,),
                  Expanded(
                    child: ListView.builder(
                      shrinkWrap: true,
                      scrollDirection: Axis.vertical,
                      itemCount: cities.length,
                      itemBuilder: (context, index) => cities[index],
                    ),
                  )
                ],
              ),
            ),
          );
        }
      
        void addCity(String city) {
          weatherData.add(Weather(city: city));
          Container toBeAddedCity = Container(
            margin: const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
            child: Text(city, style: TextStyle(fontSize: 22, color: Colors.white),),
          );
          cities.add(ColorfulBox(toBeAddedCity));
        }
      }
      

      【讨论】:

      • 非常感谢。它完美地工作。我是新手,所以我犯了可怕的错误! :)
      猜你喜欢
      • 2020-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-16
      相关资源
      最近更新 更多