颤振| 在 ListView 中使用 Listview.builder - 使整个页面可滚动

Mar*_*ert 2 listview dart flutter

我想构建一个类似 instagram 的个人资料页面,其中当前用户的所有帖子都列在提要中。在此之上,应显示有关用户的一些信息(头像、粉丝数、帖子数、个人简介等)。用户应该能够滚动整个页面。目前页面只能滚动到我的 ListView.builder 中的 sizedBox-widget 的高度。就像这样:

在此处输入图片说明

ProfilePage类的构建方法如下所示:

Widget build(BuildContext context) {

    return SafeArea(
      child: Scaffold(    
        appBar: AppBar(),
        body: ListView(    
          children: <Widget>[
           Padding(
                    padding: const EdgeInsets.only(left: 25.0, top: 30.0),
                    child: Text(_user.displayName,
                        style: TextStyle(
                            color: Colors.black,
                            fontWeight: FontWeight.bold,
                            fontSize: 20.0)),
                  ),
                  ...(all the other information for the "header-part")

                  postImagesWidget(),

            ])));}
Run Code Online (Sandbox Code Playgroud)

postImagesWidget 中,我使用 ListView.builder 来构建提要:

Widget postImagesWidget(){
return FutureBuilder(
            future: _future,
            builder:
                ((context, AsyncSnapshot<List<DocumentSnapshot>> snapshot) {
              if (snapshot.hasData) {
                if (snapshot.connectionState == ConnectionState.done) {
                  return SizedBox(
                    height: 600,
                      child: ListView.builder(
                          physics: const NeverScrollableScrollPhysics(),

                          //shrinkWrap: true,
                          itemCount: snapshot.data.length,
                          itemBuilder: ((context, index) => ListItem(
                              list: snapshot.data,
                              index: index,
                              user: _user))));
                } else {
                  return Center(
                    child: CircularProgressIndicator(),
                  );
                }
              } else {
                return Center(
                  child: CircularProgressIndicator(),
                );
              }
            }),
          );

}
Run Code Online (Sandbox Code Playgroud)

我不得不添加一个 sizedBox-Widget 来避免这个错误:

抛出了另一个异常:RenderBox 没有布局:RenderViewport#50ccf NEEDS-PAINT

这个错误的描述说我应该将shrinkwrap添加到我的ListView.builder,但是在滚动一些这个错误后这会使我的整个应用程序崩溃:

失败的断言:第 470 行 pos 12:“child.hasSize”:不正确。

如何使整个页面可滚动,而不是单独的两个部分(标题和提要)?

我知道我与事实有关,我在 ListView 中使用 ListView.builder ......

此致。

And*_*rei 6

我个人不会在 flutter 中将大小组件用于列表,只有当您希望布局的一部分在特定区域可滚动时。

但在您的情况下,我看到您希望整个页面都可以滚动,因此您有一个起点,您可以从那里设计页面的其余部分。(整个页面应该是可滚动的,所以我知道这个页面的顶部小部件应该是一个可滚动的小部件,如 SingleChildScrollView、CustomScrollView、ListView 等)

现在您的方法没有错,但需要您知道 SizedBox 的最终高度,您可以根据您的列表计算该高度。(太难)

为了解决您的问题,我使用了带有 SliverList 小部件的 CustomScrollView。

return SafeArea(
        child: Scaffold(
            appBar: AppBar(),
            body: CustomScrollView(
              slivers: <Widget>[
                SliverList(
                  delegate: SliverChildListDelegate(
                    [
                      Padding(
                        padding: const EdgeInsets.only(left: 25.0, top: 30.0),
                        child: Text(displayName,
                            style: TextStyle(
                                color: Colors.black, fontWeight: FontWeight.bold, fontSize: 20.0)),
                      ),
                    ],
                  ),
                ),
                FutureBuilder(
                  future: ApiProvider.getPictures(),
                  builder: ((context, AsyncSnapshot snapshot) {
                    if (snapshot.hasData) {
                      if (snapshot.connectionState == ConnectionState.done) {
                        return SliverList(
                            delegate: SliverChildBuilderDelegate(
                                (context, index) => Container(
                                      margin: EdgeInsets.symmetric(vertical: 10),
                                      child: Column(
                                        crossAxisAlignment: CrossAxisAlignment.start,
                                        children: <Widget>[
                                          Text(
                                            displayName,
                                            style: TextStyle(
                                                fontSize: 17, fontWeight: FontWeight.bold),
                                          ),
                                          Text(snapshot.data[index].location),
                                          Image(
                                            image: NetworkImage(snapshot.data[index].pictureUrl),
                                            width: MediaQuery.of(context).size.width,
                                          )
                                        ],
                                      ),
                                    ),
                                childCount: snapshot.data.length));
                      } else {
                        return SliverFillRemaining(
                          child: Center(
                            child: CircularProgressIndicator(),
                          ),
                        );
                      }
                    } else {
                      return SliverFillRemaining(
                        child: Center(
                          child: CircularProgressIndicator(),
                        ),
                      );
                    }
                  }),
                ),
              ],
            )));
Run Code Online (Sandbox Code Playgroud)

您的问题还有其他解决方案,但我相信这是性能方面的最佳解决方案。

如果您需要帮助,请随时寻求帮助。

  • 在第二个 SliverList 中,您可以看到我使用了 SliverChildBuilderDelegate,它在项目滚动到屏幕上时创建项目,类似于 ListView.builder。我使用它是因为您可能有很多图片要显示,因此如果您不需要它,则无需创建图像小部件。我个人在我的项目中使用了类似于 Marcel 的解决方案的代码,但从内存和性能方面来说,映射列表并将其显示在列中可能不是最有效的方式。 (2认同)