簡體   English   中英

為什么我需要將列表項包裝在一個列中,以便使用按鈕將項目動態添加到 ListView Flutter?

[英]Why do I need to wrap the list items in a Column in order to dynamically add items using a button to ListView Flutter?

在過去的一天里,我很難想出一段簡單的代碼來使用按鈕將一些項目添加到 ListView。 我想在我的應用程序中創建一個列表,只需單擊 FloatingActionButton 即可將項目添加到此列表中。
問題是當我點擊按鈕時,什么也沒發生。 但是當我 HotReloaded 應用程序時,項目神奇地出現在列表中(代碼塊 1)。
經過一番研究,我找到了一個完美的簡單解決方案。 我只是將項目包裝在Column小部件中,一切正常。 但我無法解釋為什么。 這是如何工作的? 我的初始代碼的哪一部分是錯誤的? 這與setState()方法的工作方式有關嗎? setState()究竟是如何工作的?

我的初始代碼:

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  List<Widget> items = [
    Text('initial txt'),
  ];

  void _incrementCounter() {
    setState(() {
      items.add(Text('NewText'));
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),

      body: Container(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              child: ListView(
                children: this.items,
              ),
              width: 100,
              height: 400,
              alignment: Alignment.center,
            )
          ],
        ),
        alignment: Alignment.center,
        // padding: EdgeInsets.fromLTRB(40, 10, 20, 10),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

第二個代碼:剛剛在_incrementCounter() function 中創建了一個臨時列表,並將其分配給setState()中的舊列表(我為什么要這樣做?)並將項目包裝在一個 Column 小部件中。


class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  List<Widget> items = [
    Text('initial txt'),
  ];

  void _incrementCounter() {
    List<Widget> ls_tmp = this.items;
    ls_tmp.add(Text('New Text $_counter'));

    setState(() {
      _counter++;
      this.items = ls_tmp;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),

      body: Container(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              child: ListView(
                children: [
                  Column(
                    children: this.items,
                  ),
                ],
              ),
              width: 100,
              height: 400,
              alignment: Alignment.center,
            )
          ],
        ),
        alignment: Alignment.center,
        // padding: EdgeInsets.fromLTRB(40, 10, 20, 10),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

最后但並非最不重要的一點是,還有其他解決方案嗎?

它有點隱藏在文檔中,但你可以在這里找到它:

https://api.flutter.dev/flutter/widgets/ListView/ListView.html

與框架中的其他小部件一樣,此小部件期望子列表在此處傳入后不會發生變異 有關更多詳細信息,請參閱SliverChildListDelegate.children的文檔。

在 Android Studio 中,如果 hover over children: ,那么它將顯示相同的文檔。

相反,您需要使用ListView.builder

child: ListView.builder(
  itemCount: items.length,
  itemBuilder: (BuildContext context, int index) {
    return items[index];
  },
),

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM