如何在Flutter/Dart中保存和加载两个变量?

发布于 2025-02-13 04:23:37 字数 23511 浏览 0 评论 0原文

这是我的代码:

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,以便以后我的用户可以继续游戏。但是与此同时,新游戏和继续游戏屏幕几乎相同。实际上,这是同一屏幕。唯一的区别是,当我的用户启动游戏时,变量具有以下值:

int_listCount = 0;
String assetPath = "files/main.jpg";

当我的用户单击“继续游戏”按钮时,他们应该进入同一屏幕,但是变量的值应该不同。最简单的方法是什么?

我相信我应该遵循以下步骤:

  1. 当我单击“确定”按钮到设备的内存时,保存_listCount和AssetPath变量。为此,我需要修改此代码:
      void _nextCSV() {
        setState(() {
          _listData = _listData;
          _listCount < _listData.length - 1
              ? _isFirstLoad
              ? _isFirstLoad = false
              : _listCount++
              : _listCount;
          assetPath =
          _listData[_listCount][1] == "" ? assetPath : _listData[_listCount][1];
        });
      }
  1. 当我单击“继续游戏”按钮时,从设备内存中加载_listCount和AssetPath变量的值。为此,我需要修改此代码:
    onPressed: () {
                        Navigator.push(
                          context,
                          MaterialPageRoute(builder: (context) => const NewGameRoute()),
                        );
                      },

也就是说,用户将转到newgameroute,但对于这些变量的值不同。还是创建与newgameroute几乎完全相同的持续gameroute是正确的(除了我的价值)是正确的吗?从内存中保存和加载这些值的最简单方法是什么?

编辑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);
  }

现在它非常完美。

Here is my code:

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

This experimental app consists of two screens:

Main screen:

enter image description here

Game screen:

enter image description here

I need to save 2 variables: _listCount and assetPath so that later on my users can continue the game. But at the same time, the New Game and Continue Game screens are almost identical. In fact, this is the same screen. The only difference is that when my user starts the game, the variables have the following values:

int_listCount = 0;
String assetPath = "files/main.jpg";

And when my user clicks on the "Continue game" button, they should get to the same screen, but the values of the variables should be different. What is the easiest way to do this?

I believe I should follow these steps:

  1. Save the _listCount and assetPath variables when I click the OK button to the device's memory. To do this, I need to modify this code:
      void _nextCSV() {
        setState(() {
          _listData = _listData;
          _listCount < _listData.length - 1
              ? _isFirstLoad
              ? _isFirstLoad = false
              : _listCount++
              : _listCount;
          assetPath =
          _listData[_listCount][1] == "" ? assetPath : _listData[_listCount][1];
        });
      }
  1. Load the values of the _listCount and assetPath variables from the device's memory when I click the Continue game button. To do this, I need to modify this code:
    onPressed: () {
                        Navigator.push(
                          context,
                          MaterialPageRoute(builder: (context) => const NewGameRoute()),
                        );
                      },

That is, the user will go to NewGameRoute, but with different values for these variables. Or would it be correct to create a ContinueGameRoute that is almost exactly the same as NewGameRoute (other than my values)? What is the easiest way to save and load these values from memory?

Edit 1. Using Sparsh Jain's code, I have the following:

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

Edit 2. With the help of more experienced people I modified this code yesterday. Now it looks like this and has only one error. It still doesn't work, though.

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

Now I only get one error.

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

It leads to

@override
   Widget build(BuildContext context) {
     return ListFromCSV();
   }
}

What could be the reason?

Edit 3. Here's what my code was missing:

@override
  Widget build(BuildContext context) {
    return ListFromCSV(listCount: _listCount, assetPath: assetPath);
  }

Now it works perfect.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

花辞树 2025-02-20 04:23:38

您可以将变量的值从基页传递到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(),
    );
  }
}

You can pass the value of variables from the base page to the NewGameRoute class.

can call it like, 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(),
    );
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文