【问题标题】:Horizontal ListView inside a Vertical ScrollView in FlutterFlutter中垂直滚动视图内的水平ListView
【发布时间】:2019-06-27 23:01:20
【问题描述】:

我现在正在尝试实现一种非常常见的行为,即在另一个小部件中同时具有可滚动的水平列表。想想像 IMDb 应用程序的主屏幕:

所以我想要一个可以垂直滚动的小部件,上面有很少的项目。在它的顶部,应该有一个水平的ListView,然后是一些名为motivationCard 的项目。列表和卡片之间也有一些标题。

我在我的Widget 上得到了类似的东西:

@override
  Widget build(BuildContext context) => BlocBuilder<HomeEvent, HomeState>(
        bloc: _homeBloc,
        builder: (BuildContext context, HomeState state) => Scaffold(
              appBar: AppBar(),
              body: Column(
                children: <Widget>[
                  Text(
                    Strings.dailyTasks,
                  ),
                  ListView.builder(
                    scrollDirection: Axis.horizontal,
                    itemCount: tasks.length,
                    itemBuilder: (BuildContext context, int index) =>
                        taskCard(
                          taskNumber: index + 1,
                          taskTotal: tasks.length,
                          task: tasks[index],
                        ),
                  ),
                  Text(
                    Strings.motivations,
                  ),
                  motivationCard(
                    motivation: Motivation(
                        title: 'Motivation 1',
                        description:
                        'this is a description of the motivation'),
                  ),
                  motivationCard(
                    motivation: Motivation(
                        title: 'Motivation 2',
                        description:
                        'this is a description of the motivation'),
                  ),
                  motivationCard(
                    motivation: Motivation(
                        title: 'Motivation 3',
                        description:
                        'this is a description of the motivation'),
                  ),
                ],
              ),
            ),
      );

这是我得到的错误:

I/flutter (23780): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (23780): The following assertion was thrown during performResize():
I/flutter (23780): Horizontal viewport was given unbounded height.
I/flutter (23780): Viewports expand in the cross axis to fill their container and constrain their children to match
I/flutter (23780): their extent in the cross axis. In this case, a horizontal viewport was given an unlimited amount of
I/flutter (23780): vertical space in which to expand.

我试过了:

  • Expanded 小部件包装 ListView

  • SingleChildScrollView &gt; ConstrainedBox &gt; IntrinsicHeight包裹列

  • CustomScrollView 作为父级,SliverListSliverChildListDelegate 内的列表

这些都不起作用,我继续遇到同样的错误。这是一件很常见的事情,应该不难,不知怎的,我就是无法让它工作:(

任何帮助将不胜感激,谢谢!

编辑:

我认为this 可以帮助我,但它没有。

【问题讨论】:

  • 你的垂直 ListView 在哪里?
  • 没有垂直的ListView。我希望整个屏幕都可以滚动。想想一个列,但可滚动。然后在该列中,我希望有一个水平滚动的 ListView。该列中的其余子项将是不同的项目,即标题、卡片和其他。

标签: flutter listview flutter-layout horizontal-scrolling vertical-scrolling


【解决方案1】:

好吧,您的代码可以很好地使用 ListView.builderExpanded 小部件 & 设置mainAxisSize: MainAxisSize.min,Column 小部件。

您拥有的 E.x 代码。

 body: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text(
            'Headline',
            style: TextStyle(fontSize: 18),
          ),
          Expanded(
            child: ListView.builder(
              shrinkWrap: true,
              scrollDirection: Axis.horizontal,
              itemCount: 15,
              itemBuilder: (BuildContext context, int index) => Card(
                    child: Center(child: Text('Dummy Card Text')),
                  ),
            ),
          ),
          Text(
            'Demo Headline 2',
            style: TextStyle(fontSize: 18),
          ),
          Expanded(
            child: ListView.builder(
              shrinkWrap: true,
              itemBuilder: (ctx,int){
                return Card(
                  child: ListTile(
                      title: Text('Motivation $int'),
                      subtitle: Text('this is a description of the motivation')),
                );
              },
            ),
          ),
        ],
      ),

更新:

整个页面都可以滚动 - SingleChildScrollView.

body: SingleChildScrollView(
  child: Column(
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
      Text(
        'Headline',
        style: TextStyle(fontSize: 18),
      ),
      SizedBox(
        height: 200.0,
        child: ListView.builder(
          physics: ClampingScrollPhysics(),
          shrinkWrap: true,
          scrollDirection: Axis.horizontal,
          itemCount: 15,
          itemBuilder: (BuildContext context, int index) => Card(
                child: Center(child: Text('Dummy Card Text')),
              ),
        ),
      ),
      Text(
        'Demo Headline 2',
        style: TextStyle(fontSize: 18),
      ),
      Card(
        child: ListTile(title: Text('Motivation $int'), subtitle: Text('this is a description of the motivation')),
      ),
      Card(
        child: ListTile(title: Text('Motivation $int'), subtitle: Text('this is a description of the motivation')),
      ),
      Card(
        child: ListTile(title: Text('Motivation $int'), subtitle: Text('this is a description of the motivation')),
      ),
      Card(
        child: ListTile(title: Text('Motivation $int'), subtitle: Text('this is a description of the motivation')),
      ),
      Card(
        child: ListTile(title: Text('Motivation $int'), subtitle: Text('this is a description of the motivation')),
      ),
    ],
  ),
),

【讨论】:

  • 感谢您的快速回复!我也做到了,但这并不是我所需要的。我希望 Motivation 项目不在列表中,以便整个屏幕向下滚动,这样如果滚动足够多,水平列表就会离开屏幕。关于如何实现这一目标的任何想法?
  • 太棒了,这正是我想要的。确实不复杂,谢谢!!
  • 此评论代表Roman Matroskin添加:如果水平滚动项的高度可以不同怎么办?
  • 我试图不设置使用 SizedBox 固定的列表大小,为什么当您有滚动作为父级时 shrinkWrap: true 不起作用?
【解决方案2】:

截图:


class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: 7,
        itemBuilder: (_, i) {
          if (i < 2)
            return _buildBox(color: Colors.blue);
          else if (i == 3)
            return _horizontalListView();
          else
            return _buildBox(color: Colors.blue);
        },
      ),
    );
  }

  Widget _horizontalListView() {
    return SizedBox(
      height: 120,
      child: ListView.builder(
        scrollDirection: Axis.horizontal,
        itemBuilder: (_, __) => _buildBox(color: Colors.orange),
      ),
    );
  }

  Widget _buildBox({Color color}) => Container(margin: EdgeInsets.all(12), height: 100, width: 200, color: color);
}

【讨论】:

【解决方案3】:

我们必须在另一个SingleScrollView中使用SingleScrollView,使用ListView需要固定高度

SingleChildScrollView(
   child: Column(
      children: <Widget>[
        SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: Row(
          children: [Text('H1'), Text('H2'), Text('H3')])),
        Text('V1'),
        Text('V2'),
        Text('V3')]))

【讨论】:

  • 这不是解决方案。
  • @RishabhDeepSingh 原因?我在我的应用程序中使用了它,性能比 ListView 低,但动态高度更灵活。
  • 但项目不是动态的
  • @RishabhDeepSingh 您可以创建一个文本小部件列表并将其作为与 ListView 类似的 Row 的子级传递。唯一的问题是视图没有被回收,这就是 ListView 具有更好性能的原因。我只是提供另一种选择。
【解决方案4】:

这样解决水平ListView中的垂直ListView

ListView.builder(
  itemBuilder: (context, index) =>
      Column(children: [
        _userProfileLayout(reviewPage.items[index]),
        Container(
          height: 100,
          child:
          ListView.builder( scrollDirection: Axis.horizontal,
              itemBuilder: (context, index) => Text("dddd")),
        ),
        FadeInImage.assetNetwork(
            placeholder: "images/default_review_img.png",
            image:
            "${reviewPage.items[index].multimedias[0]
                .url}"),
        _placeLayout(reviewPage.items[index])
      ]),
)
 

您也可以像这样在SingleChildScrollview 中切换到Row

ListView.builder(
  itemCount: 3,
  scrollDirection: Axis.vertical,
  itemBuilder: (context, position) {
    if (position == 0) {
      return Container(
        child: Text("First rwo"),
      );
    } else if (position == 1) {
      return Container(
        child: Text("second  rwo"),
      );
    } else if (position == 2) {
      return SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: Row(
          children: [Text("List"), Text("List"), Text("List"), Text("List")],
        ),
      );
    }
  },
)

第二个积分是Jordan Davies

【讨论】:

    【解决方案5】:

    如果有人收到超出渲染视图端口的错误。在 Container 小部件中扭曲您的 ListView 并为其提供 height 和 width 属性以解决问题

    Column(
          children: <Widget>[
            Text(
              Strings.dailyTasks,
            ),
          Container(
           height: 60,
           width: double.infinity,
            child: ListView.builder(
              scrollDirection: Axis.horizontal,
              itemCount: tasks.length,
              itemBuilder: (BuildContext context, int index) =>
                taskCard(
                  taskNumber: index + 1,
                  taskTotal: tasks.length,
                  task: tasks[index],
                 ),
             ),
           )
          ]
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-27
      • 2013-07-18
      • 2015-12-21
      • 1970-01-01
      • 1970-01-01
      • 2015-08-04
      相关资源
      最近更新 更多