如何将数据传递到Flutter/Dart中另一个屏幕的类?



我需要将两个变量的值从一个屏幕传递到另一个屏幕类。我做不到。

完整代码如下:

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),
),
),
),
);
}
}

这是我从主屏幕传递数据的方式:

GradientButton(label: 'New Game', onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const NewGameRoute(
listCount: 0, assetPath: "images/01.jpg" ///What I want to pass

)),
);
}),

这是我在另一个屏幕中获取数据的方式:

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;
...

但是当我尝试运行我的文件时,我得到以下错误:

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]),
^^^^^^^^^^

我如何将数据传递给类'_ListFromCSVState'?注意,在代码的原始版本中,我在这个类中定义了这些变量。一切都很顺利。但是我需要从主屏幕中获取这个数据的值。

提前感谢。

编辑1。现在我只有一个错误:

The named parameter 'listCount' is required, but there's no corresponding argument.

它引出了这部分代码:

@override
Widget build(BuildContext context) { // removed materialApp from here
return ListFromCSV();
}
}

ListFromCSV()用红色下划线表示。

编辑2。根据Yeasin Sheikh的建议,我这样修改了这部分代码:

@override
Widget build(BuildContext context) { // removed materialApp from here
return ListFromCSV(listCount: _listCount, assetPath: assetPath);
}

现在一切正常。我想对Prabhakaran版本的代码做同样的事情,以确保我正确理解了所有内容。

您不需要使用多个MaterialApp,只需在根部件上使用一次MaterialApp

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();
}
}

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;

也要避免使用全局上下文。您还可以检查riverpod或flutter_bloc状态管理。

你可以查看更多关于传递数据的信息

关于MaterialApp的更多信息

  1. 你不应该在一个应用程序中使用两个材质应用程序。在根级别只使用一个

  2. 使用NewGameRoute小部件是不必要的,因为它只是调用另一个小部件而没有任何业务逻辑。所以你可以删除它,从MainWidget中你可以像这样导航到listfromsv页面。

    GradientButton(label: 'New Game', onTap: () {
    Navigator.push(context,MaterialPageRoute(builder: (context) =>listfromsv (listCount: 0, assetPath: "images/01.jpg")));}),

注意:如果你不希望路由被堆叠(防止返回)使用导航器。pushReplacement代替Navigator.push

现在修改ListFromCSV小部件以接受参数。

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();
}

然后像这样访问

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();
}
}

最新更新