【问题标题】:Reverse the order a SliverFixedExtentList is built in Flutter颠倒在 Flutter 中构建 SliverFixedExtentList 的顺序
【发布时间】:2020-06-27 20:47:19
【问题描述】:

我的应用主页上有一个 FutureBuilder,它在未来完成后返回一个 SliverFixedExtentList。它看起来像这样:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:project_spruce/DataBase/DataBaseConnection.dart';
import 'package:project_spruce/states/UserState.dart';
import 'package:project_spruce/widgets/FabBottomAppBar.dart';
import 'package:project_spruce/widgets/FoodItemCard.dart';
import 'package:provider/provider.dart';

class HomeScreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    final List<DocumentSnapshot> _documents = List<DocumentSnapshot>();
    String uid = Provider.of<UserState>(context).firebaseUser.uid;
    return FutureBuilder(
      future: Provider.of<DataBaseConnection>(context).getQuerySnapshot('eatenFoods/'+ uid +'/food'),
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
        Widget child;
        if (snapshot.hasData){
          _documents.clear();
          snapshot.data.documents.forEach((doc)=> _documents.add(doc));
          child = SliverFixedExtentList(
            itemExtent: 150,
            delegate: new SliverChildBuilderDelegate(
              (context, index) => FoodItemCard(_documents[index]),
              childCount: _documents.length,
            ),
          );
        }else {
          child = SliverToBoxAdapter(child: CircularProgressIndicator());
        }
        return Scaffold(
            floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
            floatingActionButton: FloatingActionButton(
              onPressed: () => Navigator.pushNamed(context, '/camera_screen'),
              tooltip: 'Add',
              elevation: 2,
              child: Icon(Icons.add),
              backgroundColor: Theme.of(context).primaryColor,
              foregroundColor: Colors.white,
            ),
            bottomNavigationBar: FabBottomAppBar(
              backgroundColor: Theme.of(context).primaryColor,
              color: Colors.white,
              selectedColor: Colors.white,
              iconSize: 30,
              notchedShape: CircularNotchedRectangle(),
              items: [
                FabBottomAppBarItem(iconData: Icons.search, text: 'Search'),
                FabBottomAppBarItem(iconData: Icons.pie_chart, text: 'Statistics'),
                FabBottomAppBarItem(
                    iconData: Icons.storage, text: 'Food Inventory'),
                FabBottomAppBarItem(iconData: Icons.person, text: 'Profile'),
              ],
              onTabSelected: (int tabIndex) {
                switch (tabIndex) {
                  case 0:
                    {
                      // Search
                      Navigator.pushNamed(context, '/search');
                    }
                    break;
                  case 1:
                    {
                      // Statistics
                      Navigator.pushNamed(context, '/stats');
                    }
                    break;
                  case 2:
                    {
                      // Inventory
                      Navigator.pushNamed(context, '/inventory');
                    }
                    break;
                  case 3:
                    {
                      // Profile
                      Navigator.pushNamed(context, '/profile');
                    }
                    break;
                }
              },
            ),
            body: new CustomScrollView(
              slivers: <Widget>[
                SliverAppBar(
                  //title: const Text('Home Page'),
                  actions: <Widget>[
                    IconButton(
                      icon: const Icon(Icons.notifications),
                      tooltip: 'Notifications',
                      onPressed: () => (){}, //(Navigator.pushNamed(context, '/notifications')),
                    ),
                  ],
                  floating: true,
                  pinned: true,
                  snap: false,
                  forceElevated: true,
                  expandedHeight: 200.0,
                  flexibleSpace: FlexibleSpaceBar(
                    title:
                        Text("Hi, " + Provider.of<UserState>(context).user.name),
                  centerTitle: false,
                  ),
                ),
                child,
              ],
            )
            );
      }
    );
  }
}

future 从数据库中获取文档列表,然后将它们按顺序传递给将数据包装在 Card 中的辅助类。问题是这个实现将最新的文档放在底部,而我希望它们放在顶部。我可以更改从数据库Firestore.instance.collection(path).orderBy('date', descending: true).getDocuments(); 检索文档的顺序,但由于每次返回页面时列表都不会完全重建,因此除非我重建应用程序,否则新数据根本不会显示。我还尝试在自定义滚动视图中设置 reverse: true,但这会反转所有内容,包括 SliverAppBar。

有没有什么方法可以翻转 SliverFixedExtentList 的构建方式,以便更高的索引位于顶部?

【问题讨论】:

    标签: flutter reverse future flutter-sliver customscrollview


    【解决方案1】:

    您可以反转项目,而不是尝试反转 SliverFixedExtentList...您所要做的就是反转 for each 循环之后的 _documents

    注意我在哪里添加 _documents = _documents.reversed.toList() 和 setState

    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:flutter/material.dart';
    import 'package:project_spruce/DataBase/DataBaseConnection.dart';
    import 'package:project_spruce/states/UserState.dart';
    import 'package:project_spruce/widgets/FabBottomAppBar.dart';
    import 'package:project_spruce/widgets/FoodItemCard.dart';
    import 'package:provider/provider.dart';
    
    class HomeScreen extends StatefulWidget {
    
      @override
      _HomeScreenState createState() => _HomeScreenState();
    }
    
    class _HomeScreenState extends State<HomeScreen> {
      @override
      Widget build(BuildContext context) {
        final List<DocumentSnapshot> _documents = List<DocumentSnapshot>();
        String uid = Provider.of<UserState>(context).firebaseUser.uid;
        return FutureBuilder(
            future: Provider.of<DataBaseConnection>(context).getQuerySnapshot('eatenFoods/'+ uid +'/food'),
            builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
              Widget child;
              if (snapshot.hasData){
                setState(() {
                  _documents.clear();
                  snapshot.data.documents.forEach((doc)=> _documents.add(doc));
                  child = SliverFixedExtentList(
                    itemExtent: 150,
                    delegate: new SliverChildBuilderDelegate(
                          (context, index) => FoodItemCard(_documents[index]),
                      childCount: _documents.length,
                    ),
                  );
                });
              }else {
                child = SliverToBoxAdapter(child: CircularProgressIndicator());
              }
              return Scaffold(
                  floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
                  floatingActionButton: FloatingActionButton(
                    onPressed: () => Navigator.pushNamed(context, '/camera_screen'),
                    tooltip: 'Add',
                    elevation: 2,
                    child: Icon(Icons.add),
                    backgroundColor: Theme.of(context).primaryColor,
                    foregroundColor: Colors.white,
                  ),
                  bottomNavigationBar: FabBottomAppBar(
                    backgroundColor: Theme.of(context).primaryColor,
                    color: Colors.white,
                    selectedColor: Colors.white,
                    iconSize: 30,
                    notchedShape: CircularNotchedRectangle(),
                    items: [
                      FabBottomAppBarItem(iconData: Icons.search, text: 'Search'),
                      FabBottomAppBarItem(iconData: Icons.pie_chart, text: 'Statistics'),
                      FabBottomAppBarItem(
                          iconData: Icons.storage, text: 'Food Inventory'),
                      FabBottomAppBarItem(iconData: Icons.person, text: 'Profile'),
                    ],
                    onTabSelected: (int tabIndex) {
                      switch (tabIndex) {
                        case 0:
                          {
                            // Search
                            Navigator.pushNamed(context, '/search');
                          }
                          break;
                        case 1:
                          {
                            // Statistics
                            Navigator.pushNamed(context, '/stats');
                          }
                          break;
                        case 2:
                          {
                            // Inventory
                            Navigator.pushNamed(context, '/inventory');
                          }
                          break;
                        case 3:
                          {
                            // Profile
                            Navigator.pushNamed(context, '/profile');
                          }
                          break;
                      }
                    },
                  ),
                  body: new CustomScrollView(
                    slivers: <Widget>[
                      SliverAppBar(
                        //title: const Text('Home Page'),
                        actions: <Widget>[
                          IconButton(
                            icon: const Icon(Icons.notifications),
                            tooltip: 'Notifications',
                            onPressed: () => (){}, //(Navigator.pushNamed(context, '/notifications')),
                          ),
                        ],
                        floating: true,
                        pinned: true,
                        snap: false,
                        forceElevated: true,
                        expandedHeight: 200.0,
                        flexibleSpace: FlexibleSpaceBar(
                          title:
                          Text("Hi, " + Provider.of<UserState>(context).user.name),
                          centerTitle: false,
                        ),
                      ),
                      child,
                    ],
                  )
              );
            }
        );
      }
    }
    

    希望这可行

    【讨论】:

    • 这样,我遇到了与尝试按降序获取文档时相同的问题。它第一次正确构建列表,但是当添加新文档时,它成为新的 0 索引,并且由于 0 索引已经构建,它不会显示。
    • 除了for each循环,还有没有其他地方可以添加到_documents列表中?
    • 不,只是在 for each 循环中是我添加到 _documents 的地方。我首先从 Firestore 中获取快照,然后清除 _documents 列表并使用 for each 循环将每个单独的文档加载到列表中。
    • 并且反转列表对您不起作用?你能放下你的整个代码吗?
    • 是的,我已经编辑了帖子以反映完整的代码。就像我之前说的,列表的顺序是正确的,当它得到一个新的构建时,它看起来很棒。但由于它不会在每次发生变化时重新构建整个 SliverFixedExtentList,因此它不会在已构建的索引上调用构建,因此它们不会得到更新。
    猜你喜欢
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    • 2016-11-20
    • 1970-01-01
    • 2022-12-28
    • 1970-01-01
    • 2012-05-01
    相关资源
    最近更新 更多