每次在我的应用程序上获得 "passwords do not match";代码问题可能是验证或 api 请求
Getting "passwords do not match" on my app everytime; Problem with the code maybe validation or api request
我已经尝试为我的应用制作一个身份验证屏幕,但我无法注册,因为它显示密码不匹配,因为我已经设置了文本表单验证。
数据也没有出现在 firebase 身份验证中,所以我认为 API 请求可能有问题。我在 URI.parse 之后没有 put.json 进行身份验证,因为我在某个地方看到了我们没有的地方(放置后尝试但没有用)。
身份验证屏幕:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../Providers/auth.dart';
enum AuthMode { Signup, Login }
class AuthScreen extends StatelessWidget {
static const routeName = '/auth';
@override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
// final transformConfig = Matrix4.rotationZ(-8 * pi / 180);
// transformConfig.translate(-10.0);
return Scaffold(
// resizeToAvoidBottomInset: false,
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromRGBO(215, 117, 255, 1).withOpacity(0.5),
Color.fromRGBO(255, 188, 117, 1).withOpacity(0.9),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
stops: [0, 1],
),
),
),
SingleChildScrollView(
child: Container(
height: deviceSize.height,
width: deviceSize.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
child: Container(
margin: EdgeInsets.only(bottom: 20.0),
padding:
EdgeInsets.symmetric(vertical: 8.0, horizontal: 94.0),
transform: Matrix4.rotationZ(
-8 * pi / 180) //allows to rotate the container
..translate(
-10.0), //adds offset to matrix; .. operater changes the product from inside
// ..translate(-10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.deepOrange.shade900,
boxShadow: [
BoxShadow(
blurRadius: 8,
color: Colors.black26,
offset: Offset(0, 2),
)
],
),
child: Text(
'MyShop',
style: TextStyle(
color: Colors
.black, //Theme.of(context).accentTextTheme.title.color,
fontSize: 50,
fontFamily: 'Anton',
fontWeight: FontWeight.normal,
),
),
),
),
Flexible(
flex: deviceSize.width > 600 ? 2 : 1,
child: AuthCard(),
),
],
),
),
),
],
),
);
}
}
class AuthCard extends StatefulWidget {
const AuthCard({
Key? key,
}) : super(key: key);
@override
_AuthCardState createState() => _AuthCardState();
}
class _AuthCardState extends State<AuthCard> {
final GlobalKey<FormState> _formKey = GlobalKey();
AuthMode _authMode = AuthMode.Login;
Map<String, String> _authData = {
'email': '',
'password': '',
};
var _isLoading = false;
final _passwordController = TextEditingController();
Future<void> _submit() async {
if (!_formKey.currentState!.validate()) {
// Invalid!
return;
}
_formKey.currentState!.save();
setState(() {
_isLoading = true;
});
if (_authMode == AuthMode.Login) {
// Log user in
} else {
// Sign user up
await Provider.of<Auth>(context, listen: false).signup(
//as signup returns future we have to aysnc it, we do await to show loading spinner
_authData['email'].toString(),
_authData['password']
.toString()); //authdata is the value we are saviing this as
}
setState(() {
_isLoading = false;
});
}
void _switchAuthMode() {
if (_authMode == AuthMode.Login) {
setState(() {
_authMode = AuthMode.Signup;
});
} else {
setState(() {
_authMode = AuthMode.Login;
});
}
}
@override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 8.0,
child: Container(
height: _authMode == AuthMode.Signup ? 320 : 260,
constraints:
BoxConstraints(minHeight: _authMode == AuthMode.Signup ? 320 : 260),
width: deviceSize.width * 0.75,
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(labelText: 'E-Mail'),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty || !value.contains('@')) {
return 'Invalid email!';
}
return null;
},
onSaved: (value) {
_authData['email'] = value.toString();
},
),
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
obscureText:
true, //which makes sure that the inpur isnt shown to the user
validator: (value) {
if (value!.isEmpty || value.length < 5) {
return 'Password is too short!';
}
},
onSaved: (value) {
_authData['password'] = value.toString();
},
),
if (_authMode == AuthMode.Signup)
TextFormField(
enabled: _authMode == AuthMode.Signup,
decoration: InputDecoration(labelText: 'Confirm Password'),
obscureText: true,
validator: _authMode == AuthMode.Signup
? (value) {
if (value != _passwordController.text) {
return 'Passwords do not match!';
}
}
: null,
),
SizedBox(
height: 20,
),
if (_isLoading)
CircularProgressIndicator()
else
RaisedButton(
child:
Text(_authMode == AuthMode.Login ? 'LOGIN' : 'SIGN UP'),
onPressed: _submit,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
padding:
EdgeInsets.symmetric(horizontal: 30.0, vertical: 8.0),
color: Theme.of(context).primaryColor,
textColor: Theme.of(context).primaryTextTheme.button!.color,
),
FlatButton(
child: Text(
'${_authMode == AuthMode.Login ? 'SIGNUP' : 'LOGIN'} INSTEAD'),
onPressed: _switchAuthMode,
padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 4),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
textColor: Theme.of(context).primaryColor,
),
],
),
),
),
),
);
}
}
Auth.dart:
class Auth with ChangeNotifier {
late String _token;
late DateTime _expiryDate;
late String _userId;
Future<void> signup(String username, String password) async {
var url = Uri.parse(
'https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[Auth Key]');
final response = await http.post(url,
body: jsonEncode({
'username': username,
'password': password,
'returnSecureToken':
true
}));
print(json.decode(response.body));
}
}
此外,在调试控制台中没有收到任何错误消息或任何消息。在此先感谢您的帮助
如果您想使用 controller.value
.
读取值,您需要为每个 TextFormField
小部件单独设置 TextEditingController
您还必须像这样为每个 TextFormField
分配适当的控制器:
TextFormField(
controller: _controllerForThisField,
...
),
此外,不要忘记在处理小部件时正确处理所有控制器,例如在覆盖的 dispose()
方法中调用 controller.dispose()
。
我已经尝试为我的应用制作一个身份验证屏幕,但我无法注册,因为它显示密码不匹配,因为我已经设置了文本表单验证。 数据也没有出现在 firebase 身份验证中,所以我认为 API 请求可能有问题。我在 URI.parse 之后没有 put.json 进行身份验证,因为我在某个地方看到了我们没有的地方(放置后尝试但没有用)。
身份验证屏幕:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../Providers/auth.dart';
enum AuthMode { Signup, Login }
class AuthScreen extends StatelessWidget {
static const routeName = '/auth';
@override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
// final transformConfig = Matrix4.rotationZ(-8 * pi / 180);
// transformConfig.translate(-10.0);
return Scaffold(
// resizeToAvoidBottomInset: false,
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromRGBO(215, 117, 255, 1).withOpacity(0.5),
Color.fromRGBO(255, 188, 117, 1).withOpacity(0.9),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
stops: [0, 1],
),
),
),
SingleChildScrollView(
child: Container(
height: deviceSize.height,
width: deviceSize.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
child: Container(
margin: EdgeInsets.only(bottom: 20.0),
padding:
EdgeInsets.symmetric(vertical: 8.0, horizontal: 94.0),
transform: Matrix4.rotationZ(
-8 * pi / 180) //allows to rotate the container
..translate(
-10.0), //adds offset to matrix; .. operater changes the product from inside
// ..translate(-10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.deepOrange.shade900,
boxShadow: [
BoxShadow(
blurRadius: 8,
color: Colors.black26,
offset: Offset(0, 2),
)
],
),
child: Text(
'MyShop',
style: TextStyle(
color: Colors
.black, //Theme.of(context).accentTextTheme.title.color,
fontSize: 50,
fontFamily: 'Anton',
fontWeight: FontWeight.normal,
),
),
),
),
Flexible(
flex: deviceSize.width > 600 ? 2 : 1,
child: AuthCard(),
),
],
),
),
),
],
),
);
}
}
class AuthCard extends StatefulWidget {
const AuthCard({
Key? key,
}) : super(key: key);
@override
_AuthCardState createState() => _AuthCardState();
}
class _AuthCardState extends State<AuthCard> {
final GlobalKey<FormState> _formKey = GlobalKey();
AuthMode _authMode = AuthMode.Login;
Map<String, String> _authData = {
'email': '',
'password': '',
};
var _isLoading = false;
final _passwordController = TextEditingController();
Future<void> _submit() async {
if (!_formKey.currentState!.validate()) {
// Invalid!
return;
}
_formKey.currentState!.save();
setState(() {
_isLoading = true;
});
if (_authMode == AuthMode.Login) {
// Log user in
} else {
// Sign user up
await Provider.of<Auth>(context, listen: false).signup(
//as signup returns future we have to aysnc it, we do await to show loading spinner
_authData['email'].toString(),
_authData['password']
.toString()); //authdata is the value we are saviing this as
}
setState(() {
_isLoading = false;
});
}
void _switchAuthMode() {
if (_authMode == AuthMode.Login) {
setState(() {
_authMode = AuthMode.Signup;
});
} else {
setState(() {
_authMode = AuthMode.Login;
});
}
}
@override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 8.0,
child: Container(
height: _authMode == AuthMode.Signup ? 320 : 260,
constraints:
BoxConstraints(minHeight: _authMode == AuthMode.Signup ? 320 : 260),
width: deviceSize.width * 0.75,
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(labelText: 'E-Mail'),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty || !value.contains('@')) {
return 'Invalid email!';
}
return null;
},
onSaved: (value) {
_authData['email'] = value.toString();
},
),
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
obscureText:
true, //which makes sure that the inpur isnt shown to the user
validator: (value) {
if (value!.isEmpty || value.length < 5) {
return 'Password is too short!';
}
},
onSaved: (value) {
_authData['password'] = value.toString();
},
),
if (_authMode == AuthMode.Signup)
TextFormField(
enabled: _authMode == AuthMode.Signup,
decoration: InputDecoration(labelText: 'Confirm Password'),
obscureText: true,
validator: _authMode == AuthMode.Signup
? (value) {
if (value != _passwordController.text) {
return 'Passwords do not match!';
}
}
: null,
),
SizedBox(
height: 20,
),
if (_isLoading)
CircularProgressIndicator()
else
RaisedButton(
child:
Text(_authMode == AuthMode.Login ? 'LOGIN' : 'SIGN UP'),
onPressed: _submit,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
padding:
EdgeInsets.symmetric(horizontal: 30.0, vertical: 8.0),
color: Theme.of(context).primaryColor,
textColor: Theme.of(context).primaryTextTheme.button!.color,
),
FlatButton(
child: Text(
'${_authMode == AuthMode.Login ? 'SIGNUP' : 'LOGIN'} INSTEAD'),
onPressed: _switchAuthMode,
padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 4),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
textColor: Theme.of(context).primaryColor,
),
],
),
),
),
),
);
}
}
Auth.dart:
class Auth with ChangeNotifier {
late String _token;
late DateTime _expiryDate;
late String _userId;
Future<void> signup(String username, String password) async {
var url = Uri.parse(
'https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[Auth Key]');
final response = await http.post(url,
body: jsonEncode({
'username': username,
'password': password,
'returnSecureToken':
true
}));
print(json.decode(response.body));
}
}
此外,在调试控制台中没有收到任何错误消息或任何消息。在此先感谢您的帮助
如果您想使用 controller.value
.
TextFormField
小部件单独设置 TextEditingController
您还必须像这样为每个 TextFormField
分配适当的控制器:
TextFormField(
controller: _controllerForThisField,
...
),
此外,不要忘记在处理小部件时正确处理所有控制器,例如在覆盖的 dispose()
方法中调用 controller.dispose()
。