I need to pass the value of two variables from one screen to another screen class. I can't do it.
Here is the whole code:
import 'package:flutter/material.dart';
import 'package:csv/csv.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'dart:io';
//My classes
import './my classes.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Example';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Container(
child: Scaffold(
appBar: AppBar(title: const Text(_title)),
// body: const MyStatelessWidget(),
body: const MainWidget(),
),
)
);
}
}
// class MyStatelessWidget extends StatelessWidget {
// const MyStatelessWidget({Key? key}) : super(key: key);
class MainWidget extends StatefulWidget {
const MainWidget({Key? key}) : super(key: key);
@override
State<MainWidget> createState() => _MainWidgetState();
}
class _MainWidgetState extends State<MainWidget> {
CheckUserConnection _checkUserConnection = CheckUserConnection();
InternetDialogHandler _internetDialogHandler = InternetDialogHandler();
bool? _internetAvailable;
@override
void initState(){
checkNet();
super.initState();
}
void checkNet() async{
_internetAvailable = await
_checkUserConnection.checkInternetAvailability();
setState((){});
}
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
children: [
GradientButton(label: 'New Game', onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const NewGameRoute(
listCount: 0, assetPath: "images/01.jpg" ///What I want to pass
)),
);
}),
// GradientButton(label: 'Continue Game', onTap: () {
// return _internetAvailable == true ?
// {Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => const NewGameRoute()),
// )}
// :
// _internetDialogHandler.showInternetDialog(context);
// }),
],
),
Column(
children: [
GradientButton(label: 'Back Button', onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const BackRoute()),
);
// print('Button 1');
}),
GradientButton(label: 'Button 2', onTap: () {print('Button 2');}),
GradientButton(label: 'Internet', onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const InternetRoute()),
);
}),
],
)
],
),
);
}
}
//Class for a gradient button
class GradientButton extends StatelessWidget {
const GradientButton({Key? key, required this.label, required this.onTap}) : super(key: key);
final String label;
final Function onTap;
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 15),
child: GestureDetector(
onTap: () => onTap(),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(4)),
gradient: LinearGradient(
colors: <Color>[
Color(0xFF0D47A1),
Color(0xFF1976D2),
Color(0xFF42A5F5),
],
),
),
child: Text(label, style: const TextStyle(fontSize: 20, color: Colors.white, fontWeight: FontWeight.normal, decoration: TextDecoration.none),),
),
),
);
}
}
// New Game route
var globalContext; // Declare global variable to store context from StatelessWidget
// class NewGameRoute extends StatelessWidget {
// const NewGameRoute({key}); //original
class NewGameRoute extends StatelessWidget {
const NewGameRoute({
Key? key,
required int listCount,
required this.assetPath,
}) : _listCount = listCount,
super(key: key);
final int _listCount;
final String assetPath;
@override
Widget build(BuildContext context) {
globalContext = context; // globalContext receives context from StatelessWidget.
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'New Game',
home: ListFromCSV(),
);
}
}
class ListFromCSV extends StatefulWidget {
const ListFromCSV({Key? key}) : super(key: key);
@override
_ListFromCSVState createState() => _ListFromCSVState();
}
class _ListFromCSVState extends State<ListFromCSV> {
List<List<dynamic>> _listData = [
[""]
];
// int _listCount = 0;
bool _isFirstLoad = true;
// String assetPath = "files/main.jpg";
@override
void initState() {
_loadCSV();
}
// This function is only triggered at init, so we only load csv once
void _loadCSV() async {
String rawData = await rootBundle.loadString("files/Text.csv");
_listData = const CsvToListConverter().convert(rawData);
// assetPath = _listData[_listCount][1] == ""
// ? "files/main.jpg"
// : _listData[_listCount][1];
}
///
// This function is triggered when my button is pressed
void _nextCSV() {
setState(() {
_listData = _listData;
_listCount < _listData.length - 1
? _isFirstLoad
? _isFirstLoad = false
: _listCount
: _listCount;
// assetPath =
// _listData[_listCount][1] == "" ? assetPath : _listData[_listCount][1];
_listData[_listCount][1] == "" ? null : _showAlertDialog();
});
}
// This function makes buttons visible/invisible
bool isVisible = true; //will be visible for the first frame
void _isVisible() {
setState(() {
isVisible = !isVisible;
});
}
//Alert Dialog about questions and answers
Widget _answer1TextButton(){
return TextButton(
child: Text(_listData[_listCount][3]),
onPressed: () {
setState(() {
assetPath = _listData[_listCount][6];
_listCount = _listData[_listCount][2]-1;
// _listData[_listCount][0];
// _nextCSV();
print('Answer 1');
print(_listCount);
Navigator.of(globalContext).pop(); // Popping globalContext
});
},
);
}
Widget _answer2TextButton(){
return TextButton(
child: Text(_listData[_listCount][5]),
onPressed: () {
setState(() {
assetPath = _listData[_listCount][7];
_listCount = _listData[_listCount][4]-1;
print('Answer 2');
print(_listCount);
Navigator.of(globalContext).pop(); // Popping globalContext
});
},
);
}
void _showAlertDialog() {
// set up the AlertDialog
AlertDialog alert = AlertDialog(
// title: Text(),
content: Text(_listData[_listCount][1]),
actions: [
_answer1TextButton(),
_answer2TextButton(),
],
);
// show the dialog
showDialog(
barrierDismissible: false, //use to dismiss any tap on the background of the dialog
context: context,
// useRootNavigator: false, //this property needs to be added
builder: (BuildContext context) {
return WillPopScope(
onWillPop: () async {
return true; // false to disable the back button
},
child: alert,
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('New Game'),
),
body: Container(
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(assetPath),
fit: BoxFit.cover)),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Visibility(
child: Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(4),
child: Stack(
children: <Widget>[
Positioned.fill(
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('files/sheet.jpg'),
fit: BoxFit.cover)),
),
),
Text(_listData[_listCount][0]),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ImageButton(label: 'OK', onButtonTap: _nextCSV),
ImageButton(label: 'Hide', onButtonTap: _isVisible),
ImageButton(label: 'Test1', onButtonTap: _showAlertDialog),
],
),
],
),
visible: isVisible,
),
// your other widgets
Visibility(
child: ImageButton(label: 'Show', onButtonTap: _isVisible),
visible: !isVisible,
)
],
),
),
);
}
}
//Class for a cool button
class ImageButton extends StatelessWidget {
const ImageButton({Key? key, required this.label, required this.onButtonTap})
: super(key: key);
final String label;
final Function onButtonTap;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () => onButtonTap(),
child: Container(
// customize you button shape and size and design
margin: const EdgeInsets.all(8),
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 32),
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(2)),
image: DecorationImage(
image: AssetImage("files/sheet.jpg"), // you can also pass the image dynamically with variable created for the widget.
fit: BoxFit.cover)),
child: Center(
child: Text(
label,
style: const TextStyle(
color: Colors
.black, // you can get dominant colour on image and change the text color accordingly or apply shadows to the text
fontWeight: FontWeight.w500,
fontSize: 16),
),
),
),
);
}
}
This is how I pass data from the main screen:
GradientButton(label: 'New Game', onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const NewGameRoute(
listCount: 0, assetPath: "images/01.jpg" ///What I want to pass
)),
);
}),
This is how I get the data in another screen:
class NewGameRoute extends StatelessWidget {
const NewGameRoute({
Key? key,
required int listCount,
required this.assetPath,
}) : _listCount = listCount,
super(key: key);
final int _listCount;
final String assetPath;
...
But when I try to run my file I get the following errors:
Performing hot reload...
Syncing files to device sdk gphone64 x86 64...
lib/main.dart:223:7: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
_listCount < _listData.length - 1
^^^^^^^^^^
lib/main.dart:226:13: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
: _listCount
^^^^^^^^^^
lib/main.dart:226:13: Error: The setter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing setter, or defining a setter or field named '_listCount'.
: _listCount
^^^^^^^^^^
lib/main.dart:227:13: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
: _listCount;
^^^^^^^^^^
lib/main.dart:230:17: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
_listData[_listCount][1] == "" ? null : _showAlertDialog();
^^^^^^^^^^
lib/main.dart:247:29: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
child: Text(_listData[_listCount][3]),
^^^^^^^^^^
lib/main.dart:250:31: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
assetPath = _listData[_listCount][6];
^^^^^^^^^^
lib/main.dart:250:9: Error: The setter 'assetPath' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing setter, or defining a setter or field named 'assetPath'.
assetPath = _listData[_listCount][6];
^^^^^^^^^
lib/main.dart:251:32: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
_listCount = _listData[_listCount][2]-1;
^^^^^^^^^^
lib/main.dart:251:9: Error: The setter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing setter, or defining a setter or field named '_listCount'.
_listCount = _listData[_listCount][2]-1;
^^^^^^^^^^
lib/main.dart:255:15: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
print(_listCount);
^^^^^^^^^^
lib/main.dart:263:29: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
child: Text(_listData[_listCount][5]),
^^^^^^^^^^
lib/main.dart:266:31: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
assetPath = _listData[_listCount][7];
^^^^^^^^^^
lib/main.dart:266:9: Error: The setter 'assetPath' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing setter, or defining a setter or field named 'assetPath'.
assetPath = _listData[_listCount][7];
^^^^^^^^^
lib/main.dart:267:32: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
_listCount = _listData[_listCount][4]-1;
^^^^^^^^^^
lib/main.dart:267:9: Error: The setter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing setter, or defining a setter or field named '_listCount'.
_listCount = _listData[_listCount][4]-1;
^^^^^^^^^^
lib/main.dart:269:15: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
print(_listCount);
^^^^^^^^^^
lib/main.dart:281:31: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
content: Text(_listData[_listCount][1]),
^^^^^^^^^^
lib/main.dart:316:37: Error: The getter 'assetPath' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named 'assetPath'.
image: AssetImage(assetPath),
^^^^^^^^^
lib/main.dart:336:42: Error: The getter '_listCount' isn't defined for the class '_ListFromCSVState'.
- '_ListFromCSVState' is from 'package:example/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_listCount'.
Text(_listData[_listCount][0]),
^^^^^^^^^^
How do I pass data to class '_ListFromCSVState'? Note that in the original version of the code, I define these variables in this class. And everything works. But I need the value of this data to be taken from the main screen.
Thanks in advance.
CodePudding user response:
You don't need to use multiple MaterialApp
, Just use MaterialApp
once on root widget.
class NewGameRoute extends StatelessWidget {
const NewGameRoute({
Key? key,
required int listCount,
required this.assetPath,
}) : _listCount = listCount,
super(key: key);
final int _listCount;
final String assetPath;
@override
Widget build(BuildContext context) { // removed materialApp from here
return ListFromCSV();
}
}
To get variable on state class from StatefulWidget
class ListFromCSV extends StatefulWidget {
final int listCount;
const ListFromCSV({
Key? key,
required this.listCount,
}) : super(key: key);
@override
_ListFromCSVState createState() => _ListFromCSVState();
}
class _ListFromCSVState extends State<ListFromCSV> {
List<List<dynamic>> _listData = [
[""]
];
late int _listCount = widget.listCount;
Also avoid using global context. You can also check riverpod or flutter_bloc for state management.
You can check more about passing data
More about MaterialApp
CodePudding user response:
You should not use two material apps for an application. Use only one at the root level
The use of the NewGameRoute widget is not necessary as it simply calls another widget without any business logic. So you can remove that and from MainWidget you can navigate to the ListFromCSV page like this.
GradientButton(label: 'New Game', onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => ListFromCSV(listCount: 0, assetPath: "images/01.jpg")) ); }),
Note: If you don't want the route to get stacked (prevent back) use Navigator.pushReplacement instead of Navigator.push
Now modify your ListFromCSV widget to accept the params.
class ListFromCSV extends StatefulWidget {
const ListFromCSV({Key? key, required this.listCount, required assetPath}) : super(key: key);
final int listCount;
final String assetPath;
@override
_ListFromCSVState createState() => _ListFromCSVState();
}
And access it like this,
class _ListFromCSVState extends State<ListFromCSV> {
List<List<dynamic>> _listData = [
[""]
];
int _listCount = 0;
bool _isFirstLoad = true;
String assetPath = "";
@override
void initState() {
super.initState();
assetPath = widget.assetPath;
_listCount = widget.listCount;
_loadCSV();
}
}