垂直ListView内水平SingleChildScrollView

时间:2019-10-21 10:05:13

标签: flutter flutter-layout

我需要构建一个页面,其中包含以单行分组的对象列表。需要同时垂直滚动(以显示更多组)和水平滚动(以显示子组)。 垂直和水平滚动条需要完全移动项目。 像这样的东西: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宽度做到这一点?

2 个答案:

答案 0 :(得分:0)

发生错误是因为 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> <a href="#my_modal" data-toggle="modal" data-id="1">Edit</a> <div class="modal" id="my_modal"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button> <h4 class="modal-title">Click Save!</h4> </div> <div class="modal-body"> <div class="form-group"> <label for="txt" class="control-label">Text:</label> <input id="txt" class="form-control" autofocus="autofocus" placeholder="1000"/> </div> </div> <div class="modal-footer"> <button id="save" type="save" class="btn btn-primary" data-dismiss="modal">Save</button> <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button> </div> </div> </div> </div>尝试从其父级获取高度以填充整个高度时,由于r.db('database').table('users') 没有固定的容器高度值,父级返回无穷高。要解决该问题,您需要限制高度值。例如,我使用SizedBoxListView指定高度。

以下代码对我有用。

SingleChildScrollView

答案 1 :(得分:0)

请您能解释一下有关物体尺寸的猜测吗?

我有一个解决方案,但是在我的解决方案中,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