I'm relatively new to Flutter and have tried to find similar postings to help me but haven't had any luck in getting them to work for me unfortunately. I have an Android Studio program that's basically a game which involves a grid of flip cards. I have the flip cards in one dart file and the app bar in another. I have an iconbutton on the app bar which currently reduces the point count to zero, but I would also like for it to flip all of the flip cards back to their original positions when pressed. I have a global variable called resetBool that I've been trying to use, something like if resetBool == true then toggleCard() maybe. I think I might need to use a key but am having trouble implementing one properly.
Here is the code in the file which contains my appbar:
import 'package:flip_card/flip_card.dart';
import 'package:flutter/material.dart';
import 'gridone.dart' as gridone;
import 'globalVariables.dart';
import 'statenames.dart';
int count;
StateNames stateObject = new StateNames();
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home>with SingleTickerProviderStateMixin {
TabController controller;
@override
void initState() {
controller = new TabController(length: 1, vsync: this);
super.initState();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
void changeCount() {
setState(() {
counter += 1;
});
}
void decreaseCount() {
setState(() {
counter -= 1;
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title:new Text("License plate game"),
backgroundColor: Colors.greenAccent,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.autorenew,
color: Colors.white,
),
onPressed: () {
setState(() {
counter = 0;
resetBool = true;
});
},
),
Center(
child: Container(
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
child: Text('points: $counter', textAlign: TextAlign.center, style: TextStyle(fontSize: 15),
)
),
),
],
bottom: new TabBar(
controller: controller,
indicatorWeight: 5.0,
indicatorColor: Colors.green,
tabs: <Widget> [
new Tab(icon: new Icon(Icons.image),),
],
),
),
body: new TabBarView(
controller: controller,
children: <Widget>[
new gridone.GridOne(changeCount, decreaseCount),
],
)
);
}
}
And here is the code in the file which contains my flip cards:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flip_card/flip_card.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'statenames.dart';
import 'globalVariables.dart';
import 'Home.dart';
import 'gridtwo.dart' as gridTwo;
StateNames stateObject = new StateNames();
Home homeObject = new Home();
class GridOne extends StatefulWidget {
final Function updateCounter;
final Function decreaseCount;
GridOne(this.updateCounter, this.decreaseCount);
@override
_GridOneState createState() => _GridOneState();
}
class _GridOneState extends State<GridOne>
with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
int points = 0;
@override
Widget build(BuildContext context) {
super.build(context);
return new Scaffold(
body: new Column(
children: <Widget> [
new Expanded(
child: GridView.count(
crossAxisCount: 5,
children: List.generate(52, (index){
return Card(
elevation: 0.0,
margin: EdgeInsets.only(left: 3.0, right: 3.0, top: 9.0, bottom: 0.0),
color: Color(0x00000000),
child: FlipCard(
direction: FlipDirection.HORIZONTAL,
speed: 1000,
//(resetBool == true) ? cardKey.currentState.toggleCard() : null,
onFlipDone: (status) {
setState(() {
(status)
? widget.decreaseCount()
: widget.updateCounter();
});
if (counter == 25) {
Fluttertoast.showToast(
msg: "You've got 25 states! Wow!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM_LEFT,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
};
print(counter);
},
front: Container(
decoration: BoxDecoration(
color: Color(0xFF006666),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
FittedBox(fit:BoxFit.fitWidth,
child: Text(stateObject.stateNames[index], style: TextStyle(fontFamily: 'Architects Daughter', color: Colors.white), )
//Theme.of(context).textTheme.headline
),
Text('',
style: Theme.of(context).textTheme.body1),
],
),
),
back: Container(
decoration: BoxDecoration(
color: Color(0xFF006666),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image(image: AssetImage(stateObject.licensePlatePaths[index])),
//Text('',
//style: Theme.of(context).textTheme.body1),
],
),
),
),
);
})
)
)
]
),
);
}
}
The solution is to use currentState.toggleCard(); for the cards that are facing Back when the IconButton is clicked.
Basically, what I did is I gave keys to each card at initState method.
List<GlobalKey<FlipCardState>> cardKeys = [];
@override
void initState() {
List.generate(52, (index) {
cardKeys.add(GlobalKey<FlipCardState>());
});
super.initState();
}
Don't forget to put the key to widget
FlipCard(key: cardKeys[index], ... )
Then, call resetCards method below when the button is clicked. If the card is facing back then toggle logic.
void resetCards() {
cardKeys.forEach((element) {
if (!element.currentState.isFront) {
element.currentState.toggleCard();
}
});
setState(() {});
}
You need to call a method on the parent widget, that would be triggered in the child widget. For that, please check this stackoverflow link
Full working code:
import 'package:flutter/material.dart';
import 'package:flip_card/flip_card.dart';
import 'package:fluttertoast/fluttertoast.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
// This makes the visual density adapt to the platform that you run
// the app on. For desktop platforms, the controls will be smaller and
// closer together (more dense) than on mobile platforms.
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Home(),
);
}
}
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
TabController controller;
int counter = 0;
final GridOneController myController = GridOneController();
@override
void initState() {
controller = new TabController(length: 1, vsync: this);
super.initState();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
void changeCount() {
setState(() {
counter += 1;
});
}
void decreaseCount() {
setState(() {
counter -= 1;
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("License plate game"),
backgroundColor: Colors.greenAccent,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.autorenew,
color: Colors.white,
),
onPressed: () {
setState(() {
counter = 0;
myController.resetCards();
});
},
),
Center(
child: Container(
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
child: Text(
'points: $counter',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 15),
)),
),
],
bottom: new TabBar(
controller: controller,
indicatorWeight: 5.0,
indicatorColor: Colors.green,
tabs: <Widget>[
new Tab(
icon: new Icon(Icons.image),
),
],
),
),
body: new TabBarView(
controller: controller,
children: <Widget>[
new GridOne(counter, myController),
],
));
}
}
class GridOneController {
void Function() resetCards;
}
class GridOne extends StatefulWidget {
int counter;
final GridOneController controller;
GridOne(this.counter, this.controller);
@override
_GridOneState createState() => _GridOneState(controller);
}
class _GridOneState extends State<GridOne> {
_GridOneState(GridOneController _controller) {
_controller.resetCards = resetCards;
}
int points = 0;
void increaseCounter() {
widget.counter += 1;
}
void decreaseCounter() {
widget.counter -= 1;
}
void resetCards() {
cardKeys.forEach((element) {
if (!element.currentState.isFront) {
element.currentState.toggleCard();
}
});
setState(() {});
}
List<GlobalKey<FlipCardState>> cardKeys = [];
@override
void initState() {
List.generate(52, (index) {
cardKeys.add(GlobalKey<FlipCardState>());
});
super.initState();
}
@override
Widget build(BuildContext context) {
print(cardKeys.length);
return new Scaffold(
body: new Column(children: <Widget>[
new Expanded(
child: GridView.count(
crossAxisCount: 5,
children: List.generate(52, (index) {
return Card(
elevation: 0.0,
margin: EdgeInsets.only(
left: 3.0, right: 3.0, top: 9.0, bottom: 0.0),
color: Color(0x00000000),
child: new FlipCard(
key: cardKeys[index],
direction: FlipDirection.HORIZONTAL,
speed: 1000,
onFlipDone: (status) {
setState(() {
(status) ? decreaseCounter() : increaseCounter();
});
if (widget.counter == 25) {
Fluttertoast.showToast(
msg: "You've got 25 states! Wow!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM_LEFT,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
;
print(widget.counter);
},
front: Container(
decoration: BoxDecoration(
color: Color(0xFF006666),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
FittedBox(
fit: BoxFit.fitWidth,
child: Text(
'FRONT',
style: TextStyle(color: Colors.white),
)
//Theme.of(context).textTheme.headline
),
Text(
'',
),
],
),
),
back: Container(
decoration: BoxDecoration(
color: Color(0xFF006666),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Text('BACK')],
),
),
),
);
})))
]),
);
}
}