简体   繁体   English

渲染时嵌套的ListView.Builder失败-Flutter

[英]Nested ListView.Builder fails while rendering - Flutter

I am trying a flutter app to build a small game I have a List<List<ColumnData>> gameBoard where ColumnData is a locally defined class. 我正在尝试使用flutter应用程序构建一个小型游戏,我有一个List<List<ColumnData>> gameBoard ,其中ColumnData是本地定义的类。 The list is supposed to be a 2-D list in triangle format eg for a level as 3 the list will look like: 该列表应该是三角形格式的二维列表,例如,级别为3时,列表将如下所示:

[00] [00]
[10][11] [10] [11]
[20][21][22] [20] [21] [22]

My simulation code is: 我的模拟代码是:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}
class ColumnData {
  int _rowIdx;
  int _colIdx;
  String _data;
  Widget _column;

  ColumnData({String data, int row, int col}) {
    _data = data;
    _rowIdx = row;
    _colIdx = col;
    _column = new InkWell(
      child: new Container(
        margin: new EdgeInsets.all(10.0),
        child: new SizedBox(width: 30.0, height: 30.0,
          child: new Text(_data, textAlign: TextAlign.center),
        ),
        decoration: new BoxDecoration(
          border: new Border.all(color: Colors.indigoAccent, width: 2.0),
          shape: BoxShape.rectangle,
        ),
      ),
    );
  }
  set data(String value) => _data=value;
  set colIdx(int value) => _colIdx=value;
  set rowIdx(int value) => _rowIdx=value;
  Widget get column => _column;
  String get data => _data;
  int get colIdx => _colIdx;
  int get rowIdx => _rowIdx;
  String toString(){
    return ('Row: ${_rowIdx} Col: ${_colIdx} Data: $_data');
  }
}

class _MyHomePageState extends State<MyHomePage> {
  List<List<ColumnData>> gameBoard = new List(3);

  @override
  void initState() {
    super.initState();
    print('Lets build matrix');
    initGame();
  }
  @override
  Widget build(BuildContext context) {
    return new Scaffold(body: _buildBody());
  }

  Widget _buildBody() {
    return  new ListView.builder(
      scrollDirection: Axis.horizontal,
      itemCount: gameBoard.length,
      shrinkWrap: true,
      itemBuilder: (BuildContext ctx, int rowIdx){
        return new ListView.builder(
          scrollDirection: Axis.vertical,
          shrinkWrap: true,
          itemCount: gameBoard[rowIdx].length,
          itemBuilder: (BuildContext ctx, int colIdx){
            return gameBoard[rowIdx][colIdx].column;
          },
        );
      },
    );
  }

  initGame(){
    List<ColumnData> row1Data = [];
    List<ColumnData> row2Data = [];
    List<ColumnData> row3Data = [];
    ColumnData colData00 = new ColumnData(row: 0, col: 0, data: '7');
    row1Data.add(colData00);
    gameBoard[0] =row1Data;
    ColumnData colData10 = new ColumnData(row: 1, col: 0, data: '5');
    ColumnData colData11 = new ColumnData(row: 1, col: 1, data: '2');
    row2Data.add(colData10);
    row2Data.add(colData11);
    gameBoard[1]= row2Data;
    ColumnData colData20 = new ColumnData(row: 2, col: 0, data: '3');
    ColumnData colData21 = new ColumnData(row: 2, col: 1, data: '2');
    ColumnData colData22 = new ColumnData(row: 2, col: 2, data: '0');
    row3Data.add(colData20);
    row3Data.add(colData21);
    row3Data.add(colData22);
    gameBoard[2] = row3Data;
    print(gameBoard);
  }

}

The snippet of the error that I am getting is: 我收到的错误摘要是:

I/flutter (21273): [[Row: 0 Col: 0 Data: 7], [Row: 1 Col: 0 Data: 5, Row: 1 Col: 1 Data: 2], [Row: 2 Col: 0 Data: 3, Row: 2 Col: 1 Data: 2, Row: 2 Col: 2 Data: 0]]
Restarted app in 9,341ms.
I/flutter (21273): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (21273): The following assertion was thrown during performLayout():
I/flutter (21273): 'package:flutter/src/rendering/viewport.dart': Failed assertion: line 1283 pos 16:
I/flutter (21273): 'constraints.hasBoundedWidth': is not true. 
I/flutter (21273): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter (21273): more information in this error message to help you determine and fix the underlying cause.
I/flutter (21273): In either case, please report this assertion by filing a bug on GitHub: 
I/flutter (21273):   https://github.com/flutter/flutter/issues/new
I/flutter (21273): When the exception was thrown, this was the stack:
I/flutter (21273): #2      RenderShrinkWrappingViewport.performLayout (package:flutter/src/rendering/viewport.dart)
I/flutter (21273): #3      RenderObject.layout (package:flutter/src/rendering/object.dart:1570:7)
......

I have tried without shrinkwrap and also by using rows and columns but no success 我尝试了不使用wrinkwrap,也使用行和列,但是没有成功

What exactly am I doing wrong? 我到底在做什么错? Any other variations that I can explore? 我可以探索其他任何变化吗? Any other work-around/idea to build the 2-D matrix 建立二维矩阵的任何其他解决方法/想法

Any pointers welcom 任何指针欢迎

Regards 问候

ListView inside ListView is a bad idea to begin with. ListView内的ListView是一个坏主意。

This is a typical use-case for CustomScrollView . 这是CustomScrollView的典型用例。 Where you can combine multiple scrollview into one single unit. 您可以在其中将多个滚动视图组合为一个单元。 And still have that smooth virtualized rendering where only what's visible is rendered on screen. 而且仍然具有平滑的虚拟化渲染 ,其中只有可见的内容在屏幕上渲染。

This tranform your build method into the following : 这会将您的build方法转换为以下内容:

@override
Widget build(BuildContext context) {
  final slivers = new List<Widget>(gameBoard.length);

  for (var i = 0; i < gameBoard.length; i++) {
    slivers[i] = new SliverList(
      delegate: new SliverChildBuilderDelegate((context, j) {
        return gameBoard[i][j].column;
      }, childCount: gameBoard[i].length),
    );
  }
  return new Scaffold(
    body: new CustomScrollView(
      shrinkWrap: true,
      slivers: slivers,
    ),
  );
}

Since my game area had finite numbers of rows and columns (designed based on level selected and some other parameters), I was able to achieve my layout with following: 由于我的游戏区域具有有限数量的行和列(根据所选的关卡和其他一些参数设计),因此我可以通过以下方式实现布局:

Widget _buildBody() {
    List<Widget> rows = new List<Widget>(gameBoard.length);
    for (int i=0;i<gameBoard.length; i++){
      List<Widget> cols = new List<Widget>(gameBoard[i].length);
      for(int j=0; j<gameBoard[i].length; j++){
        cols[j] = gameBoard[i][j].column;
      }
      rows[i] = new Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: cols,
      );
    }

    return new Container(
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: rows,
      ),
    );
}

After this the output is 在此之后的输出是

在此处输入图片说明

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

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