我的代码显示并提交登录表单:
class LoginWidget extends StatelessWidget {
const LoginWidget({
super.key,
});
@override
Widget build(BuildContext context) {
final citiesLoaded = context.select((LoginBloc bloc) => bloc.state.citiesLoaded);
final loginBloc = context.read<LoginBloc>();
final selectedCity = (citiesLoaded && loginBloc.state.cities.length == 1)
? loginBloc.state.cities[0]
: context.select((LoginBloc bloc) => bloc.state.selectedCity);
final formValidator = context.select((LoginBloc bloc) => bloc.state.formValidator);
final theme = Theme.of(context).extension<LoginPageThemeData>();
return AutofillGroup(
child: Column(
children: [
citiesLoaded
? Visibility(
visible: loginBloc.state.cities.length > 1,
child: CitySelectWidget(selectedCity: selectedCity),
)
: const BusyWidget(status: 'Loading cities'),
Text('Username:'),
TextFormField(
autofillHints: const [AutofillHints.username, AutofillHints.email, AutofillHints.name],
enabled: selectedCity != null,
initialValue: loginBloc.state.username,
keyboardType: TextInputType.emailAddress,
decoration: theme?.inputDecoration
?.copyWith(errorText: formValidator.usernameField.isValid ? null : formValidator.usernameField.validationMessage),
onChanged: (value) => loginBloc.add(SetUsernameEvent(username: value))),
Text('Password:'),
TextFormField(
autofillHints: const [AutofillHints.username, AutofillHints.email, AutofillHints.name],
enabled: selectedCity != null,
initialValue: loginBloc.state.password,
obscureText: true,
decoration: theme?.inputDecoration
?.copyWith(errorText: formValidator.passwordField.isValid ? null : formValidator.passwordField.validationMessage),
onChanged: (value) => loginBloc.add(SetPasswordEvent(password: value))),
ElevatedButton(
onPressed: selectedCity == null
? null
: () {
context.read<app_bloc.AppBloc>().add(app_bloc.SetSelectedCityEvent(selectedCity));
context.read<LoginBloc>().add(const AuthEvent());
},
child: Text('Sign in'),
),
],
),
);
}
}
在父小部件(登录页面)中显示主应用程序的页面,当自动过程完成时:
@override
Widget build(BuildContext context) {
return BlocListener<LoginBloc, LoginState>(
listenWhen: (previous, current) => previous.isLogged != current.isLogged || (current.loginFailed && !current.isBusy),
listener: (context, state) {
if (state.isLogged) {
Navigator.pushNamedAndRemoveUntil(context, '/home', (route) => false);
}
if (state.loginFailed) {
Fluttertoast.showToast(msg: state.statusMessage);
}
},
child: Scaffold( ......
因此,在提交时,身份验证成功后,将设置
isLogged
标志,并且应用程序导航到主主页+销毁登录页面。但自动填充仍然不起作用。没有提示保存密码。
你知道我还需要做什么吗?
自动填充功能似乎存在一些问题,有时是由于设备类型、操作系统和系统设置造成的。
自动填充服务提供商严重依赖自动填充提示。确保当前使用的自动填充服务支持 autofillHints 中的条目(该服务的名称通常可以在您的移动设备的系统设置中找到)。
在开发过程中排除自动填充问题,为许多用户提供最适合的解决方案。
但一般来说,要获得最佳体验:
某些自动填充提示仅适用于特定的键盘类型。例如,AutofillHints.name 需要 TextInputType.name,而 AutofillHints.email 仅适用于 TextInputType.emailAddress。确保输入字段具有兼容的键盘类型。根据经验,TextInputType.name 与 iOS 上预定义的许多自动填充提示配合得很好。
这样你就可以拥有
/
Text('Username:'),
TextFormField(
autofillHints: const [AutofillHints.email, AutofillHints.name],
enabled: selectedCity != null,
initialValue: loginBloc.state.username,
keyboardType: TextInputType.emailAddress,
decoration: theme?.inputDecoration
?.copyWith(errorText: formValidator.usernameField.isValid ? null : formValidator.usernameField.validationMessage),
onChanged: (value) => loginBloc.add(SetUsernameEvent(username: value))),
Text('Password:'),
TextFormField(
keyboardType: TextInputType.visiblePassword,
autofillHints: const [AutofillHints.password],
enabled: selectedCity != null,
initialValue: loginBloc.state.password,
obscureText: true,
decoration: theme?.inputDecoration
?.copyWith(errorText: formValidator.passwordField.isValid ? null : formValidator.passwordField.validationMessage),
onChanged: (value) => loginBloc.add(SetPasswordEvent(password: value))),
/