使用参数导航 – DART 3

huangapple go评论72阅读模式
英文:

Navigate with arguments - DART 3

问题

I try to use the official documentation of Flutter to pass arguments.
我尝试使用Flutter的官方文档来传递参数。

I need some help.
我需要一些帮助。

The documentation: https://docs.flutter.dev/cookbook/navigation/navigate-with-arguments
文档链接:https://docs.flutter.dev/cookbook/navigation/navigate-with-arguments

Maybe it's about I use a stateful class, and the documentation uses only stateless?
也许问题出在我使用了有状态的类,而文档中只使用了无状态的类?

main.dart:
主要文件(main.dart):

import 'dart:io';

import 'package:chope_ton_diplome/screens/PassArgumentsScreen.dart';
import 'package:chope_ton_diplome/screens/ScreenArguments.dart';
import 'package:flutter/material.dart';
import 'package:chope_ton_diplome/screens/Auth.dart';
import 'package:chope_ton_diplome/screens/Password.dart';
import 'package:chope_ton_diplome/screens/Term.dart';
import 'package:firebase_core/firebase_core.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  Platform.isAndroid
      ? await Firebase.initializeApp(
          options: const FirebaseOptions(
            apiKey: "YOUR_API_KEY",
            appId: "YOUR_APP_ID",
            messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
            projectId: "YOUR_PROJECT_ID",
          ),
        )
      : await Firebase.initializeApp();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Chope Ton BTS',
      debugShowCheckedModeBanner: false,
      initialRoute: "/",
      routes: {
        '/': (context) => const AuthScreen(),
        '/TermScreen': (context) => const TermScreen(email: ''),
        '/PasswordScreen': (context) => const PasswordScreen(),
      },
    );
  }
}

PassArgumentsScreen.dart:
PassArgumentsScreen.dart文件:

import 'package:flutter/cupertino.dart';

class PassArgumentsScreen extends StatelessWidget {
  static const routeName = '/TermScreen';

  final String email;

  const PassArgumentsScreen({
    Key? key,
    required this.email,
  });

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    throw UnimplementedError();
  }
}

ScreenArguments.dart:
ScreenArguments.dart文件:

class ScreenArguments {
  final String _email;

  ScreenArguments(this._email);
}

Auth.dart:
Auth.dart文件:

import 'package:chope_ton_diplome/screens/Guest.dart';
import 'package:chope_ton_diplome/screens/Password.dart';
import 'package:chope_ton_diplome/screens/Term.dart';
import 'package:chope_ton_diplome/screens/ScreenArguments.dart';
import 'package:chope_ton_diplome/screens/PassArgumentsScreen.dart';
import 'package:flutter/material.dart';

import 'PassArgumentsScreen.dart';
import 'ScreenArguments.dart';

class AuthScreen extends StatefulWidget {
  static const routeName = '/';

  @override
  State<AuthScreen> createState() => _AuthScreenState();
}

class _AuthScreenState extends State<AuthScreen> {
  final GlobalKey<FormState> _authKey = GlobalKey<FormState>();
  final RegExp emailRegex = RegExp(r"[a-z0-9\.-]+@[a-z0-9\._-]+\.[a-z]+");
  String _email = '';

  @override
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context)!.settings.arguments as AuthScreen;

    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text(args.email),
        ),
        body: Center(
          child: SingleChildScrollView(
            padding: const EdgeInsets.symmetric(horizontal: 20.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                RichText(
                  text: TextSpan(
                    text: 'Bienvenue sur'.toUpperCase(),
                    style: const TextStyle(color: Colors.black, fontSize: 30.0),
                    children: [
                      TextSpan(
                        text: 'ChopeTonDiplome'.toUpperCase(),
                        style: TextStyle(
                          color: Theme.of(context).primaryColor,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ],
                  ),
                ),
                const Text(
                  'Esquive la case "Pôle emploi"',
                  style: TextStyle(
                    fontStyle: FontStyle.italic,
                  ),
                ),
                const SizedBox(
                  height: 50.0,
                ),
                Form(
                  key: _authKey,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      const Text('Entre ton email'),
                      const SizedBox(
                        height: 10.0,
                      ),
                      TextFormField(
                        onChanged: (value) => setState(() => _email = value),
                        validator: (value) =>
                            value!.isEmpty || !emailRegex.hasMatch(value)
                                ? "Merci d'entrer une adresse email valide"
                                : null,
                        decoration: InputDecoration(
                          hintText: 'Ex: john.walter@domaine.fr',
                          border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(0.0),
                            borderSide: const BorderSide(color: Colors.grey),
                          ),
                          focusedBorder: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(0.0),
                            borderSide: const BorderSide(color: Colors.grey),
                          ),
                        ),
                      ),
                      const SizedBox(
                        height: 10.0,
                      ),
                      ElevatedButton(
                        style: ElevatedButton.styleFrom(
                          elevation: 0,
                          backgroundColor: Theme.of(context).primaryColor,
                          padding: const EdgeInsets.symmetric(
                            vertical: 15.0,
                          ),
                        ),
                        onPressed: !emailRegex.hasMatch(_email)
                            ? null
                            : () {
                                if (_authKey.currentState!.validate()) {
                                  print(_email);
                                  Navigator.pushNamed(
                                    context,
                                    PassArgumentsScreen.routeName,
                                    arguments: ScreenArguments(
                                      _email,
                                    ),
                                  );
                                }
                              },
                        child: Text(
                          'continue'.toUpperCase(),
                          style: const TextStyle(
                            color: Colors.white,
                          ),
                        ),
                      ),
                      ElevatedButton(
                        style: ElevatedButton.styleFrom(
                          elevation: 0,
                          backgroundColor: Theme.of(context).primaryColor,
                          padding: const EdgeInsets.symmetric(
                            vertical: 15.0,
                          ),
                        ),
                        onPressed: !emailRegex.hasMatch(_email)
                            ? null
                            : () {
                                if (_authKey.currentState!.validate()) {
                                  print(_email);
                                  Navigator.pushNamed(
                                    context,
                                    TermScreen.routeName,
                                    arguments: ScreenArguments(
                                      _email,
                                    ),
                                  );
                                }
                              },
                        child: Text(
                          'continue'.toUpperCase(),
                          style: const TextStyle(
                            color: Colors.white,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Tried to apply the official documentation, but I got some difficulties.
尝试应用官方文档,但遇到了一些困难。

英文:

I try to use the official documentation of Flutter to pass arguments.
I need some help.
The documentation : https://docs.flutter.dev/cookbook/navigation/navigate-with-arguments
Maybe it's about i use statefull class and the documentation use only stateless?
main.dart :

`import &#39;dart:io&#39;;
import &#39;package:chope_ton_diplome/screens/PassArgumentsScreen.dart&#39;;
import &#39;package:chope_ton_diplome/screens/ScreenArguments.dart&#39;;
import &#39;package:flutter/material.dart&#39;;
import &#39;package:chope_ton_diplome/screens/Auth.dart&#39;;
import &#39;package:chope_ton_diplome/screens/Password.dart&#39;;
import &#39;package:chope_ton_diplome/screens/Term.dart&#39;;
import &#39;package:firebase_core/firebase_core.dart&#39;;
Future&lt;void&gt; main() async {
WidgetsFlutterBinding.ensureInitialized();
Platform.isAndroid
? await Firebase.initializeApp(
options: const FirebaseOptions(
apiKey:&quot;AIzaSyDqCXX9h8O4ieJPPCIeqCzs3UUarhDWWEk&quot;,
appId:&quot;1:150239692586:android:0a00b7f597f48794b5c053&quot;,
messagingSenderId:&quot;150239692586&quot;,
projectId:&quot;chopetonbts-16bc8&quot;,
),
)
: await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: &#39;Chope Ton BTS&#39;,
debugShowCheckedModeBanner: false,
initialRoute: &quot;/&quot;,
routes: {
&#39;/&#39;: (context) =&gt; const AuthScreen(),
&#39;/TermScreen&#39;: (context) =&gt; const TermScreen(email: &#39;&#39;,),
&#39;/PasswordScreen&#39;: (context) =&gt; const PasswordScreen(),
},
);
}
}`

PassArgumentsScreen.dart :

`import &#39;package:flutter/cupertino.dart&#39;;
class PassArgumentsScreen extends StatelessWidget {
static const routeName = &#39;/TermScreen&#39;;
final String email;
const PassArgumentsScreen({
super.key,
required this.email,
});
@override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}
`

ScreenArguments.dart :

`
class ScreenArguments {
final String _email;
ScreenArguments(this._email);
}
`

Auth.dart :

``
import &#39;package:chope_ton_diplome/screens/Guest.dart&#39;;
import &#39;package:chope_ton_diplome/screens/Password.dart&#39;;
import &#39;package:chope_ton_diplome/screens/Term.dart&#39;;
import &#39;package:chope_ton_diplome/screens/ScreenArguments.dart&#39;;
import &#39;package:chope_ton_diplome/screens/PassArgumentsScreen.dart&#39;;
import &#39;package:flutter/material.dart&#39;;
import &#39;PassArgumentsScreen.dart&#39;;
import &#39;ScreenArguments.dart&#39;;
class AuthScreen extends StatefulWidget {
//const AuthScreen({super.key});
//final Function(int) onChangedStep;
static const routeName = &#39;/&#39;;
Function(int) onChangedStep(int i) {
// TODO: implement onChangeStep
throw UnimplementedError();
}
const AuthScreen({super.key, onChangedStep});
//const AuthScreen({required Key? key, required this.onChangeStep,}) : super(key: key);
@override
State&lt;AuthScreen&gt; createState() =&gt; _AuthScreenState();
}
class _AuthScreenState extends State&lt;AuthScreen&gt; {
final GlobalKey&lt;FormState&gt; _authKey = GlobalKey&lt;FormState&gt;();
final RegExp emailRegex = RegExp(r&quot;[a-z0-9\.-]+@[a-z0-9\._-]+\.[a-z]+&quot;);
String email= &#39;&#39;;
@override
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguments as AuthScreen;
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text(args.email),
),
body: Center(
//monte le champ lorsque l&#39;on &#233;crit
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
text: &#39;Bienvenue sur\n&#39;.toUpperCase(),
style: const TextStyle(color: Colors.black, fontSize: 30.0),
children: [
TextSpan(
text: &#39;ChopeTonDiplome&#39;.toUpperCase(),
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
),
),
],
),
),
const Text(
&#39;Esquive la case &quot;P&#244;le emploi&quot;&#39;,
style: TextStyle(
fontStyle: FontStyle.italic,
),
),
const SizedBox(
height: 50.0,
),
Form(
key: _authKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(&#39;Entre ton email&#39;),
const SizedBox(
height: 10.0,
),
TextFormField(
onChanged: (value) =&gt; setState(() =&gt; _email = value),
validator: (value) =&gt; value!.isEmpty || !emailRegex.hasMatch(value) ? &quot;Merci d&#39;entrer une adresse email valide&quot; : null,
decoration: InputDecoration(
hintText: &#39;Ex: john.walter@domaine.fr&#39;,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(0.0),
borderSide: const BorderSide(color: Colors.grey),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(0.0),
borderSide: const BorderSide(color: Colors.grey),
),
),
),
const SizedBox(
height: 10.0,
),
ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0,
backgroundColor: Theme.of(context).primaryColor,
padding: const EdgeInsets.symmetric(
vertical: 15.0,
),
),
onPressed:  !emailRegex.hasMatch(_email) ? null : () {
if(_authKey.currentState!.validate()) {
print(_email);
Navigator.pushNamed(context, PassArgumentsScreen.routeName,
arguments: ScreenArguments(
_email,
),
);
//widget.onChangedStep(1);
/*
Navigator.push(context, MaterialPageRoute(builder: (context) =&gt; const TermScreen()
)
);*/
}
},
child: Text(
&#39;continue&#39;.toUpperCase(),
style: const TextStyle(
color: Colors.white,
),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0,
backgroundColor: Theme.of(context).primaryColor,
padding: const EdgeInsets.symmetric(
vertical: 15.0,
),
),
onPressed:  !emailRegex.hasMatch(_email) ? null : () {
if(_authKey.currentState!.validate()) {
print(_email);
Navigator.pushNamed(context, TermScreen.routeName,
arguments: ScreenArguments(
_email,
),
);
//widget.onChangedStep(1);
/*
Navigator.push(context, MaterialPageRoute(builder: (context) =&gt; const TermScreen()
)
);*/
}
},
child: Text(
&#39;continue&#39;.toUpperCase(),
style: const TextStyle(
color: Colors.white,
),
),
),
],
),
),
],
),
),
),
),
);
}
}`

Tried to apply the official documentation, but i go some difficulties.
Thanks

答案1

得分: 1

请使用以下翻译好的部分:

忘记文档,尝试这个,你应该使用`onGenerateRoute`。在这里,我为你创建了两个类,`RouteConsts`包含了所有屏幕的常量,`RouteGenerator`包含了生成函数并返回相应的路由。

class RouteConsts {
  static const String initialScreen = '/';
  static const String homeScreen = '/homeScreen';
  static const String termsScreen = '/TermsScreen';
  static const String passwordScreen = '/PasswordScreen';
}

class RouteGenerator {
  static Route generate(RouteSettings s) {
    Widget page;
    switch (s.name) {
      case RouteConsts.homeScreen:
        HomeScreenArguments args = s.arguments as HomeScreenArguments;
        page = HomeScreen(email: args.email);
        break;
      default:
        page = const Center(
          child: Text('无效路由'),
        );
        break;
    }

    return MaterialPageRoute(builder: (context) => page);
  }
}

并在主文件中像这样使用它:

class MyApp extends StatelessWidget {
  const MyApp({Key? key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Chope Ton BTS',
      debugShowCheckedModeBanner: false,
      initialRoute: "/",
      onGenerateRoute: RouteGenerator.generate, // <- 这里是RouteGenerator类
    );
  }
}

RouteGenerator中,你可以看到我使用了HomeScreenArguments,这是一个模型类,其参数与你的屏幕完全相同。在我的代码中,我将此模型放在无状态或有状态类之上,像这样:

class HomeScreenArguments {
  final String email;

  HomeScreenArguments({required this.email});
}

class HomeScreen extends StatefulWidget {
  final String email;

  const HomeScreen({
    Key? key,
    required this.email,
  });

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  late final String localEmail;

  @override
  void initState() {
    /// 就像这样,你可以创建一个局部变量并获取其值。
    localEmail = widget.email;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      /// 或者你可以直接像这样使用它。
      child: Text(widget.email),
    );
  }
}

在导航时,你可以像这样传递值:

class SecondScreen extends StatelessWidget {
  const SecondScreen({Key? key});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        Navigator.pushNamed(
          context,
          RouteConsts.homeScreen,
          arguments: HomeScreenArguments(email: 'working@dart.flutter'),
        );
      },
      child: const Text('导航'),
    );
  }
}

希望对你有所帮助。

英文:

Forget the docs try this, you should use onGenerateRoute. here i'm making you two classes RouteConsts which have constants for your all screens and RouteGenerator which have the generate function and return the routes accordingly.

class RouteConsts {
static const String initialScreen = &#39;/&#39;;
static const String homeScreen = &#39;/homeScreen&#39;;
static const String termsScreen = &#39;/TermsScreen&#39;;
static const String passwordScreen = &#39;/PasswordScreen&#39;;
}
class RouteGenerator {
static Route generate(RouteSettings s) {
Widget page;
switch (s.name) {
case RouteConsts.homeScreen:
HomeScreenArguments args = s.arguments as HomeScreenArguments;
page = HomeScreen(email: args.email);
break;
default:
page = const Center(
child: Text(&#39;Invalid route&#39;),
);
break;
}
return MaterialPageRoute(builder: (context) =&gt; page);
}
}

and use it in main like this:

class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: &#39;Chope Ton BTS&#39;,
debugShowCheckedModeBanner: false,
initialRoute: &quot;/&quot;,
onGenerateRoute: RouteGenerator.generate,  // &lt;- here is the RouteGenerator class 
);
}
}

In RouteGenerator you can see i have used HomeScreenArguments that's the model class having the exact same arguments as your screen, in my code i do like this i make this model above the stateless or stateful class. like this:

class HomeScreenArguments {
final String email;
HomeScreenArguments({required this.email});
}
class HomeScreen extends StatefulWidget {
final String email;
const HomeScreen({
super.key,
required this.email,
});
@override
State&lt;HomeScreen&gt; createState() =&gt; _HomeScreenState();
}
class _HomeScreenState extends State&lt;HomeScreen&gt; {
late final String localEmail;
@override
void initState() {
/// Here like this you can take a local variable and get the value.
localEmail = widget.email;
super.initState();
}
@override
Widget build(BuildContext context) {
return Center(
/// Or you can use directly use it like this.
child: Text(widget.email),
);
}
}

and on navigating you can give values like this:

class SecondScreen extends StatelessWidget {
const SecondScreen({super.key});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, RouteConsts.homeScreen,
arguments: HomeScreenArguments(email: &#39;working@dart.flutter&#39;));
},
child: const Text(&#39;Navigate&#39;));
}
}

Hope it'll help you.

huangapple
  • 本文由 发表于 2023年7月20日 20:36:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76729954.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定