英文:
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 '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:"AIzaSyDqCXX9h8O4ieJPPCIeqCzs3UUarhDWWEk",
appId:"1:150239692586:android:0a00b7f597f48794b5c053",
messagingSenderId:"150239692586",
projectId:"chopetonbts-16bc8",
),
)
: 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: 'Chope Ton BTS',
debugShowCheckedModeBanner: false,
initialRoute: "/",
routes: {
'/': (context) => const AuthScreen(),
'/TermScreen': (context) => const TermScreen(email: '',),
'/PasswordScreen': (context) => const PasswordScreen(),
},
);
}
}`
PassArgumentsScreen.dart :
`import 'package:flutter/cupertino.dart';
class PassArgumentsScreen extends StatelessWidget {
static const routeName = '/TermScreen';
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 '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 {
//const AuthScreen({super.key});
//final Function(int) onChangedStep;
static const routeName = '/';
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<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(
//monte le champ lorsque l'on écrit
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
text: 'Bienvenue sur\n'.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,
),
);
//widget.onChangedStep(1);
/*
Navigator.push(context, MaterialPageRoute(builder: (context) => const TermScreen()
)
);*/
}
},
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,
),
);
//widget.onChangedStep(1);
/*
Navigator.push(context, MaterialPageRoute(builder: (context) => const TermScreen()
)
);*/
}
},
child: Text(
'continue'.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 = '/';
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('Invalid route'),
);
break;
}
return MaterialPageRoute(builder: (context) => 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: 'Chope Ton BTS',
debugShowCheckedModeBanner: false,
initialRoute: "/",
onGenerateRoute: RouteGenerator.generate, // <- 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<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
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: 'working@dart.flutter'));
},
child: const Text('Navigate'));
}
}
Hope it'll help you.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论