Currently, I have a String with 12 words which is extracted from an Argument
from another page:
Widget build(BuildContext context) {
final String seed = ModalRoute.of(context).settings.arguments;
I then split the String and shuffle them into an Array which then display as MaterialButton
in a GridView
. I need that when the user click on a MaterialButton
it will add the splitted word into another String Array which then display in a Container
above the GridView
. The GridView
is built by using a for
loop to add MaterialButton
to <Widget>[]
which call a setState()
to change a bool value which in turn change the appearance of the button and add the word into the Container. At first I had trouble when clicking on a button, the setState()
is called thus refreshing the whole page and reshuffle the word, but after finding Update a part of the UI on Flutter I wrap my MaterialButton
in a StatefulBuilder
and preventing it from rebuilding the whole page. But that also stop the Text
in the container above from updating. What can I do so that when the user click a button, it change it appearance and also update the Text in the Container above?
Here is my code so far:
import 'package:flutter/material.dart';
import 'package:myapp/color_utils.dart';
class SeedConfirmPage extends StatefulWidget {
SeedConfirmPage({Key key, this.title}) : super(key: key);
final String title;
@override
_SeedConfirmPageState createState() => _SeedConfirmPageState();
}
class _SeedConfirmPageState extends State<SeedConfirmPage> {
List<bool> clicked = [
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false
];
@override
Widget build(BuildContext context) {
final String seed = ModalRoute.of(context).settings.arguments;
List<String> seedArray = seed.split(" ")..shuffle();
final seedChip = <Widget>[];
List<String> seedText = [];
for (var i = 0; i < seedArray.length; i++) {
seedChip.add(StatefulBuilder(builder: (BuildContext context, setState) {
return MaterialButton(
color: clicked[i] ? colorBlack : Colors.white,
textColor: clicked[i] ? Colors.white : colorBlack,
minWidth: MediaQuery.of(context).size.width,
height: 32,
child: Text(
seedArray[i],
style: TextStyle(fontSize: 12),
),
onPressed: () {
setState(() {
clicked[i] = !clicked[i];
if (clicked[i]) {
seedText.add(seedArray[i]);
} else {
seedText.remove(seedArray[i]);
}
});
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
);
}));
}
return Scaffold(
appBar: AppBar(
backgroundColor: splashBG,
leading: BackButton(color: Colors.white),
title: Text("Back"),
),
backgroundColor: splashBG,
body: Container(
padding: EdgeInsets.only(
left: 16,
right: 16,
),
child: Column(
children: <Widget>[
Flexible(
child: Container(
width: MediaQuery.of(context).size.width / 2,
child: Image(
image: AssetImage('assets/images/logo_1.png'),
),
),
),
Container(
height: 120,
padding: EdgeInsets.all(32.0),
margin: EdgeInsets.only(top: 28, bottom: 28),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8), color: colorBlack),
child: Center(
child: Text(
seedText.toString(),
style: TextStyle(color: Colors.white),
),
),
),
Container(
width: MediaQuery.of(context).size.width,
height: 120,
child: GridView.count(
crossAxisCount: 4,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 5),
children: seedChip,
),
),
],
),
),
);
}
}
I know this is not optimal to check the state of the button to know whether it is click or not. So a side question is what can I do to check the if the button has been clicked yet?
EDIT
Here is the screenshot of what I am trying to archive:
Before user press:
After user press: