水平滚动的SingleChildScrollView中嵌套竖直方向的ListView

7
我需要创建一个页面,其中包含按单行分组的对象列表。需要垂直和水平滚动以显示更多的分组和分组子项。垂直和水平滚动需要同时移动所有项目。类似于这样:https://gph.is/g/46gjW0q 我使用以下代码来实现这一点:
Widget _buildGroups() {
    return SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: Container(
        width: 2000,
        child: ListView.builder(
          scrollDirection: Axis.vertical,
          itemCount: boardData.length,
          itemBuilder: (context, index) {
            return Row(children: _buildSingleGroup(index));
          },
        ),
      ),
    );
}

List<Widget> _buildSingleGroup(int groupIndex) {
    return List.generate(...);
}

我需要这个元素在水平方向上具有动态性,但是如您所见,如果不设置宽度,会导致错误:

══════════════════ Exception caught by rendering library ═════════════════════
The following assertion was thrown during performResize()
Vertical viewport was given unbounded width.

Viewports expand in the cross axis to fill their container and constrain their 
children to match their extent in the cross axis. In this case, a vertical 
viewport was given an unlimited amount of horizontal space in which to expand.

我尝试在ListView中设置"shrinkWrap: true",但结果出现了另一个错误:

Failed assertion: line 1629 pos 16: 'constraints.hasBoundedWidth': is not true.

那么如何使用动态的ListView宽度来实现这个呢?

1
你为什么不使用嵌套的ListView呢?一个带有垂直滚动条的ListView,里面再放置另一个带有水平滚动条的ListView。 - Gino
嗨@吉诺,如果我按照你说的那样做,每一行都会自己滚动,这不是我想要的行为。 - Davide Bicego
我还应该提到,我需要使用ListView小部件,以便我可以实现loadMoreRows函数来加载更多数据,并且如果可能的话,不要使Flutter重新加载页面中的所有小部件。我已经使用SingleChildScrollViews和Lists实现了所需的结果,但这不能以有效的方式处理loadMoreRows。 - Davide Bicego
2个回答

2
错误的原因是当 ListView 尝试从其父级获取高度以填充整个高度时,父级返回无限高度,因为 SingleChildScrollView 没有固定的容器高度值。要解决此问题,您需要限制高度值。例如,我使用 SizedBox 来为 ListView 指定高度。

以下代码适用于我。

SingleChildScrollView(
  child: Column(
    mainAxisSize: MainAxisSize.min,
    crossAxisAlignment: CrossAxisAlignment.start,
    children: <Widget>[
      SizedBox(
        height: 120, // <-- you should put some value here
        child: ListView.builder(
          scrollDirection: Axis.horizontal,
          itemCount: items.length,
          itemBuilder: (context, index) {
            return Text('it works');
          },
        ),
      ),
    ],
  ),
);

-2
请问您能否解释一下您对对象大小的猜测?
我有一个解决方案,但在我的解决方案中,Flutter将为第一帧构建所有对象(在两个轴上)。并且在三个轴上任何setState都会再次构建。所以这不是一个好的解决方案。
最后的水平滚动偏移量enter image description hereenter image description here。但我还是会解释一下。
///
class BothAxisScroll extends StatefulWidget {
  @override
  _BothAxisScrollState createState() => _BothAxisScrollState();
}

class _BothAxisScrollState extends State<BothAxisScroll> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        padding: const EdgeInsets.all(30),
        child: Container(
          alignment: Alignment.topLeft,
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: SingleChildScrollView(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: _build(),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

List<Widget> _build() {
  return List.generate(
      20,
      (index) => Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.start,
            children: _buildSingleGroup(index),
          ));
}

List<Widget> _buildSingleGroup(int _index) {
  return List.generate(
    Random().nextInt(20),
    (index) {
      print('BUILD: $_index');
      return Container(
          padding: const EdgeInsets.all(15), child: Text("$_index-$index"));
    },
  );
}

并在第一帧中得出结果:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接