Flutter中的水平ListView和垂直ScrollView

xxls0lw8  于 2023-05-19  发布在  Flutter
关注(0)|答案(9)|浏览(203)

我正在尝试实现一个非常常见的行为,现在这是有一个横向列表中的另一个小部件,在同一时间滚动。想象一下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小部件 Package ListView
  • 使用SingleChildScrollView > ConstrainedBox > IntrinsicHeight Package 列
  • 父节点为CustomScrollViewSliverListSliverChildListDelegate中的List

这些都不起作用,我继续得到同样的错误。这是一个非常常见的事情,不应该有任何困难,不知何故,我只是不能让它工作:(
任何帮助将不胜感激,谢谢!
编辑:
我以为this可以帮助我,但它没有。

a7qyws3x

a7qyws3x1#

好吧,你的代码工作正常,用Expanded Widget Package 你的-ListView.builder并设置Column Widget的mainAxisSize: MainAxisSize.min,
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')),
      ),
    ],
  ),
),

ifsvaxew

ifsvaxew2#

截图:

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);
}
6ojccjat

6ojccjat3#

我们必须在另一个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')]))
yhuiod9q

yhuiod9q4#

如果有人得到renderview端口被超出错误。扭曲容器小部件中的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],
             ),
         ),
       )
      ]
)
kt06eoxx

kt06eoxx5#

我尝试在此代码,我修复了我的问题,我希望解决你想要它.

SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: Row(
            children: [
              item(),
              item(),
              item(),
              item(),
            ],
          ),
        ),
g6ll5ycj

g6ll5ycj6#

对于Web Chome,你必须添加MaterialScrollBehavior才能水平滚动。see(Horizontal listview not scrolling on web but scrolling on mobile)我演示了如何使用scrollcontroller来左右移动列表。

import 'package:flutter/gestures.dart';
class MyCustomScrollBehavior extends MaterialScrollBehavior {
  // Override behavior methods and getters like dragDevices
  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
      };
}

return MaterialApp(
      title: 'Flutter Demo',
      scrollBehavior: MyCustomScrollBehavior(),
)

class TestHorizontalListView extends StatefulWidget {
  TestHorizontalListView({Key? key}) : super(key: key);

  @override
  State<TestHorizontalListView> createState() => _TestHorizontalListViewState();
}

class _TestHorizontalListViewState extends State<TestHorizontalListView> {
  List<String> lstData=['A','B','C','D','E','F','G'];
  
  final ScrollController _scrollcontroller = ScrollController();

_buildCard(String value)
{
  return Expanded(child:Container(
    margin: const EdgeInsets.symmetric(vertical: 20.0),
    width:300,height:400,child:Card(child: Expanded(child:Text(value,textAlign: TextAlign.center, style:TextStyle(fontSize:30))),)));
}

void _scrollRight() {
    _scrollcontroller.animateTo(
      _scrollcontroller.position.maxScrollExtent,
      duration: Duration(seconds: 1),
      curve: Curves.fastOutSlowIn,
    );
  }

void _scrollLeft() {
    _scrollcontroller.animateTo(
      0,
      duration: Duration(seconds: 1),
      curve: Curves.fastOutSlowIn,
    );
  }
_segment1()
{
  return     SingleChildScrollView(child:
    Expanded(child:
        Container(height:300,
          width:MediaQuery.of(context).size.width,
          child:Row(children: [
          FloatingActionButton.small(onPressed: _scrollRight, child: const Icon(Icons.arrow_right),),
          Expanded(child:Scrollbar(child:ListView.builder(
            itemCount: lstData.length,
            controller: _scrollcontroller,
            scrollDirection: Axis.horizontal,
            itemBuilder:(context,index)
            {
              return _buildCard(lstData[index]);
            })
          ,),
        ),
        FloatingActionButton.small(onPressed: _scrollLeft, child: const Icon(Icons.arrow_left),),
    ]))
    ,
    )
    );

}
@override
  void initState() {
    //   TODO: implement initState
    super.initState();

  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: Text("horizontal listview",)),body: 
    segment1(),
);
  }
}
btxsgosb

btxsgosb7#

你只需要固定你的Listview的高度(例如,通过将它 Package 在SizedBox中)。
这是因为在绘制框架之前无法知道列表视图的内容。想象一下一张有几百个项目的清单。没有办法直接知道它们中的最大高度。

cgfeq70w

cgfeq70w8#

使用Builder在垂直列表视图中添加水平列表视图

没有一个答案被证明可以解决我的问题,即在垂直ListView中有一个水平ListView,同时仍然使用ListBuilder(这比简单地一次呈现所有子元素更高效)。

结果很简单。只需将垂直列表的子列表 Package 在Column中,并检查index是否为0(或index % 3 == 0),然后呈现水平列表。
似乎工作得很好:

final verticalListItems = [];
final horizontalListItems = [];

ListView.builder(
  shrinkWrap: true,
  itemCount: verticalListItems.length,
  itemBuilder: (context, vIndex) {
    final Chat chat = verticalListItems[vIndex];

    return Column( // Wrap your child inside this column
      children: [
        // And then conditionally render your Horizontal list
        if (vIndex == 0) ListView.builder(itemCount: horizontalListItems.length itemBuilder: (context, hIndex) => Text('Horizontal List $hIndex')),

        // Vertical list
        Text('Item No. $vIndex')
      ],
    );
  },
),
ioekq8ef

ioekq8ef9#

试试物理学:BouncingScrollPhysics()

如果您在ListView -垂直滚动中使用ListView -水平滚动,则可能会导致子ListView过度滚动的问题。在这种情况下,我使用的是physics: BouncingScrollPhysics()的子ListView,它提供了一个很好的弹跳滚动效果,并解决了我的错误

相关问题