I have a stateful widget that has a simple grid and each grid cell has a container inside it.
I would like to click on a cell / container and have its content changed.
The problem is that the GestureDetector -> onTap method gets triggered on app refresh for all cels.
In the example below, the _changeCell
method gets triggered instantly for all cels and onTap
doesn't work.
Any ideas?
import 'package:flutter/material.dart';
class GridWidget extends StatefulWidget {
@override
_GridWidgetState createState() => new _GridWidgetState();
}
class _GridWidgetState extends State<GridWidget> {
@override
Widget build(BuildContext context) {
Color cellColor = Colors.white;
Text cellText = new Text('');
// when a cell is tapped, change the color and text
_changeCell(index) {
setState(() {
cellColor = Colors.lightBlue;
cellText = new Text('clicked');
});
print("Container clicked " + index.toString());
}
// create a 5 by 5 grid
return new GridView.count(
crossAxisCount: 5,
children: new List.generate(5, (index) {
return new GestureDetector(
onTap: _changeCell(index),
child: new Container(
width: double.infinity,
height: double.infinity,
decoration: new BoxDecoration(
color: cellColor,
),
child: new Center(
child: cellText,
),
),
);
}),
);
}
}
just change onTap: _changeCell(index)
to onTap: () => _changeCell(index)
. _changeCell(index) this returns null and you setting null to onTap and calling the same function .
below code is for this
I played around a little bit.
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new DemoScreen(),
));
}
class DemoScreen extends StatefulWidget {
@override
_DemoScreenState createState() => new _DemoScreenState();
}
class _DemoScreenState extends State<DemoScreen> {
Color cellColor = Colors.white;
Text _getText(index) {
Text text;
switch (index) {
case 0:
text = new Text('lightBlue');
break;
case 1:
text = new Text('red');
break;
case 2:
text = new Text('green');
break;
case 3:
text = new Text('yellow');
break;
case 4:
text = new Text('orange');
break;
default:
text = new Text('brown');
break;
}
return text;
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Demo App"),
),
body: new GridView.count(
crossAxisCount: 5,
children: new List.generate(5, (index) {
return new MyWidget(
index: index,
color: cellColor,
text: _getText(index),
);
}),
),
);
}
}
class MyWidget extends StatefulWidget {
final Color color;
final Text text;
final int index;
MyWidget({this.color, this.text, this.index});
@override
_MyWidgetState createState() => new _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
Color cellColor = Colors.white;
Text cellText = new Text('white');
@override
void initState() {
super.initState();
cellColor = widget.color;
cellText = widget.text;
}
_changeCell(index) {
setState(() {
switch (index) {
case 0:
cellColor = Colors.lightBlue;
cellText = new Text('lightBlue');
break;
case 1:
cellColor = Colors.red;
cellText = new Text('red');
break;
case 2:
cellColor = Colors.green;
cellText = new Text('green');
break;
case 3:
cellColor = Colors.yellow;
cellText = new Text('yellow');
break;
case 4:
cellColor = Colors.orange;
cellText = new Text('orange');
break;
default:
cellColor = Colors.brown;
cellText = new Text('brown');
break;
}
});
print("Container clicked " + index.toString());
}
@override
Widget build(BuildContext context) {
return new GestureDetector(
onTap: () => _changeCell(widget.index),
child: new Container(
margin: new EdgeInsets.symmetric(horizontal: 1.0),
width: double.infinity,
height: double.infinity,
decoration: new BoxDecoration(
color: cellColor,
),
child: new Center(
child: cellText,
),
),
);
}
}
Hope it helps :)
There's a problem in your code at this line:
onTap: _changeCell(index),
Basically, instead of setting onTap to a method, you're calling the method directly and setting onTap to the result of that call (null). Each time the widget builds, it will call the function.
What you should be doing is this:
onTap: () => _changeCell(index)
TLDR answer for those looking for a quick fix.
Change:
onTap: () => myMethod,
To this:
onTap: (){ myMethod();},
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With