繁体   English   中英

如何在 Flutter 实现 Nested ListView.builder?

[英]How to implemented Nested ListView.builder in Flutter?

我已经看过这篇文章

对于嵌套滚动,但根据官方 flutter 频道的视频中的解释,不是正确的方法

我想实现以下布局

在此处输入图像描述

列表 header,如 Claim requested credentials、Claim received credentials、Pending Requests 等是动态的,将来自后端。 此外,列表 header 中的每个项目,如模块 1:设计金融服务,也是动态的

所以我需要列表中的列表

我正在使用 CustomScroll 但我无法实现内部列表视图

我正在寻找一个惰性列表选项,而不仅仅是将内部列表映射到列或列表上,因为内部列表可能包含 100 个项目

这是我取得的成就

在此处输入图像描述

这是示例代码

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          HeaderGradient(),
          Positioned(
            top: 110,
            left: 0,
            right: 0,
            bottom: 0,
            child: Container(
              padding: const EdgeInsets.all(8.0),
              decoration: const BoxDecoration(
                color: grayColor,
                borderRadius: BorderRadius.only(
                  topLeft: Radius.circular(20),
                  topRight: Radius.circular(20),
                ),
              ),
              child: CustomScrollView(
                slivers: [
                  const SliverToBoxAdapter(
                    child: ManageCredentialHeader(),
                  ),
                  SliverList(
                      delegate: SliverChildBuilderDelegate((context, index) {
                    return ManageCredentialCard();
                  }, childCount: 10))
                ],
              ),
            ),
          )
        ],
      ),
    );
  }
}

class ManageCredentialCard extends StatelessWidget {
  const ManageCredentialCard({super.key});

  @override
  Widget build(BuildContext context) {
    return Card(
      color: Theme.of(context).colorScheme.background,
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
        child: Column(
          children: [
            const ManageCredentialCardHeader(),

            const ManageCredentialCardItem()
          ],
        ),
      ),
    );
  }
}

ManageCredentialCardItem是内部列表

一旦我将ManageCredentialCardItem包装在ListView.builder ,我就会收到错误提示

RenderFlex children have non-zero flex but incoming height constraints are
unbounded.
When a column is in a parent that does not provide a finite height constraint,
for example if it is
in a vertical scrollable, it will try to shrink-wrap its children along the
vertical axis. Setting a
flex on a child (e.g. using Expanded) indicates that the child is to expand to
fill the remaining
space in the vertical direction.

检查示例 repo以检查我尝试过的内容和完整的源代码

要解决“ListView.builder”问题,我建议将其包装成“Expanded”并将“ListView”的“shrinkWrap”属性设置为 true。

至于列表问题中的列表,我不确定我是否理解正确,但是将内部列表的“主要”属性设置为 false 应该可以使它跟随一般列表的滚动并避免在内部滚动。

可能还需要将 'shrinkWrap' 设置为 true,因为它没有定义高度,使其不懒惰,但我会尝试用 'Expanded' 包装它,因为它可能有相同的结果保持它懒惰

正如@Yeasin Sheikh 所建议的,您不需要在ManageCredentialCardItem中使用Listview.builder ,因为ManageCredentialCardItem的父级正在处理滚动,即

 SliverList(    // 👈 This will handle scroll
      delegate: SliverChildBuilderDelegate((context, index) {
          return ManageCredentialCard(); //👈 So you can use column instead
       },childCount: 10))

如果您有必须使用ListView.builder从远程源获取结果的用例,则可以在ListView.builder中使用shrinkWrap: true prop

我不太确定你想要达到什么效果,但是:

如果您的目标是像这样在您的ManageCredentialCard中显示完整的项目列表:

在此处输入图像描述

您只需要使用以下内容更新ManageCredentialCard小部件

class ManageCredentialCard extends StatelessWidget {
  const ManageCredentialCard({super.key});

  @override
  Widget build(BuildContext context) {
    return Card(
      color: Theme.of(context).colorScheme.background,
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
        child: Column(
          children: [
            const ManageCredentialCardHeader(),
            ListView.builder(
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              itemBuilder: (context, index) {
                return const ManageCredentialCardItem();
              },
              itemCount: 20,
            )
            // const ManageCredentialCardItem()
          ],
        ),
      ),
    );
  }
}

如果您的目标是限制Cards的大小,并且能够像这样滚动 Items 列表

在此处输入图像描述

您必须使用SizeBox为您的卡片定义高度限制。

class ManageCredentialCard extends StatelessWidget {
  const ManageCredentialCard({super.key});

  @override
  Widget build(BuildContext context) {
    return Card(
      color: Theme.of(context).colorScheme.background,
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
        child: Column(
          children: [
            const ManageCredentialCardHeader(),
            SizedBox(
              height: 150,
              child: ListView.builder(
                shrinkWrap: true,
                physics: const ClampingScrollPhysics(),
                itemBuilder: (context, index) {
                  return const ManageCredentialCardItem();
                },
                itemCount: 10,
              ),
            )
            // const ManageCredentialCardItem()
          ],
        ),
      ),
    );
  }
}

您唯一需要做的就是在到达其中一个内部列表的Listview时滚动主列表视图。
为此,您可以使用NotificationListener小部件,如本文所述:
Flutter:ListView:当子 ListView 到达底部时滚动父 ListView - ClampingScrollPhysics 在大小容器中不起作用

我指的是在条子上生成所有东西

child: CustomScrollView(
  slivers: [
    const SliverToBoxAdapter(
      child: ManageCredentialHeader(),
    ),
    for (int i = 0; i < 10; i++)
      SliverPadding(
        padding: const EdgeInsets.symmetric(
            horizontal: 8, vertical: 4),
        sliver: SliverList(
          delegate: SliverChildBuilderDelegate(
              childCount: 10 + 1, //extend by 1 for header
              (context, index) {
            return index == 0
                ? const ManageCredentialCardHeader()
                : const ManageCredentialCardItem();
          }),
        ),
      )
  ],
),

您还可以为儿童创建自定义条子。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM