Reputation: 1028
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.
The list is supposed to be a 2-D list in triangle format
e.g. for a level as 3 the list will look like:
[00]
[10][11]
[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
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
Upvotes: 1
Views: 2664
Reputation: 1028
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
Upvotes: 1
Reputation: 277047
ListView
inside ListView
is a bad idea to begin with.
This is a typical use-case for 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 :
@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,
),
);
}
Upvotes: 1