![](/img/trans.png)
[英]How do i use flutter variables from main.dart in other screen.dart files in the same lib folder?
[英]How to save and load two variables in the same screen in Flutter/Dart?
這是我的代碼:
import 'package:flutter/material.dart';
import 'package:csv/csv.dart';
import 'package:flutter/services.dart' show rootBundle;
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(),
),
)
);
}
}
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(height: 30),
ClipRRect(
borderRadius: BorderRadius.circular(4),
child: Stack(
children: <Widget>[
Positioned.fill(
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: <Color>[
Color(0xFF0D47A1),
Color(0xFF1976D2),
Color(0xFF42A5F5),
],
),
),
),
),
TextButton(
style: TextButton.styleFrom(
padding: const EdgeInsets.all(16.0),
primary: Colors.white,
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const NewGameRoute()),
);
},
child: const Text('New Game'),
),
],
),
),
const SizedBox(height: 30),
ClipRRect(
borderRadius: BorderRadius.circular(4),
child: Stack(
children: <Widget>[
Positioned.fill(
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: <Color>[
Color(0xFF0D47A1),
Color(0xFF1976D2),
Color(0xFF42A5F5),
],
),
),
),
),
TextButton(
style: TextButton.styleFrom(
padding: const EdgeInsets.all(16.0),
primary: Colors.white,
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const NewGameRoute()),
);
},
child: const Text('Continue Game'),
),
],
),
),
],
),
);
}
}
// New Game route
class NewGameRoute extends StatelessWidget {
const NewGameRoute({key});
@override
Widget build(BuildContext context) {
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];
});
}
// This function makes buttons visible/invisible
bool isVisible = true; //will be visible for the first frame
void _isVisible() {
setState(() {
isVisible = !isVisible;
});
}
@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),
],
),
],
),
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),
),
),
),
);
}
}
這個實驗性應用由兩個屏幕組成:
主屏幕:
游戲畫面:
我需要保存 2 個變量:_listCount 和assetPath,以便以后我的用戶可以繼續游戲。 但與此同時,New Game 和 Continue Game 屏幕幾乎完全相同。 其實這是同一個畫面。 唯一的區別是當我的用戶開始游戲時,變量具有以下值:
int_listCount = 0;
String assetPath = "files/main.jpg";
當我的用戶點擊“繼續游戲”按鈕時,他們應該進入同一個屏幕,但變量的值應該不同。 最簡單的方法是什么?
我相信我應該遵循以下步驟:
void _nextCSV() {
setState(() {
_listData = _listData;
_listCount < _listData.length - 1
? _isFirstLoad
? _isFirstLoad = false
: _listCount++
: _listCount;
assetPath =
_listData[_listCount][1] == "" ? assetPath : _listData[_listCount][1];
});
}
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const NewGameRoute()),
);
},
也就是說,用戶將轉到 NewGameRoute,但這些變量的值不同。 或者創建一個與 NewGameRoute 幾乎完全相同(除了我的值)的 ContinueGameRoute 是否正確? 從內存中保存和加載這些值的最簡單方法是什么?
編輯 1.使用Sparsh Jain的代碼,我有以下內容:
Launching lib\main.dart on sdk gphone64 x86 64 in debug mode...
Running Gradle task 'assembleDebug'...
lib/main.dart:168:7: Error: Expected an identifier, but got ':'.
Try inserting an identifier before ':'.
: super(key: key);
^
lib/main.dart:168:24: Error: Expected '}' before this.
: super(key: key);
^
lib/main.dart:172:3: Error: Expected '{' before this.
final int _listCount;
^^^^^
lib/main.dart:75:23: Error: No named parameter with the name '_listCount'.
_listCount: 0, assetPath: "images/01.jpg" ///What I want to pass
^^^^^^^^^^
lib/main.dart:164:3: Context: Found this candidate, but the arguments don't match.
NewGameRoute(
^^^^^^^^^^^^
lib/main.dart:85:69: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
Try using a constructor or factory that is 'const'.
MaterialPageRoute(builder: (context) => const NewGameRoute()),
^^^^^^^^^^^^
lib/main.dart:168:20: Error: Undefined name 'key'.
: super(key: key);
^^^
lib/main.dart:168:9: Error: Method invocation is not a constant expression.
: super(key: key);
^^^^
lib/main.dart:172:13: Error: Final field '_listCount' is not initialized.
Try to initialize the field in the declaration or in every constructor.
final int _listCount;
^^^^^^^^^^
lib/main.dart:174:16: Error: Final field 'assetPath' is not initialized.
Try to initialize the field in the declaration or in every constructor.
final String assetPath;
^^^^^^^^^
FAILURE: Build failed with an exception.
* Where:
Script 'D:\flutter\packages\flutter_tools\gradle\flutter.gradle' line: 1156
* What went wrong:
Execution failed for task ':app:compileFlutterBuildDebug'.
> Process 'command 'D:\flutter\bin\flutter.bat'' finished with non-zero exit value 1
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 9s
Exception: Gradle task assembleDebug failed with exit code 1
編輯 2.在更有經驗的人的幫助下,我昨天修改了這段代碼。 現在它看起來像這樣,並且只有一個錯誤。 但是,它仍然不起作用。
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
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();
}
}
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;
// 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);
}
// 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),
),
),
),
);
}
}
現在我只得到一個錯誤。
The named parameter 'assetPath' is required, but there's no corresponding argument.
它導致
@override
Widget build(BuildContext context) {
return ListFromCSV();
}
}
可能是什么原因?
編輯 3.這是我的代碼丟失的內容:
@override
Widget build(BuildContext context) {
return ListFromCSV(listCount: _listCount, assetPath: assetPath);
}
現在它完美無缺。
您可以將variables
的值從基本頁面傳遞給NewGameRoute
類。
可以這樣稱呼它, NewGameRoute(10, "abc.csv");
class NewGameRoute extends StatelessWidget {
NewGameRoute(
{Key? key,
required this. _listCount,
required this. assetPath,
: super(key: key);
final int _listCount;
final String assetPath;
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'New Game',
home: ListFromCSV(),
);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.