我的代码显示并提交登录表单:
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
标志将设置在认证成功后,应用程序导航到主主页+销毁登录页面。但自动填充仍然不工作。没有提示保存密码。
你知道我还需要做什么吗?
2条答案
按热度按时间f8rj6qna1#
自动填充功能似乎存在一些问题,有时是由于设备类型,操作系统和系统设置。
自动填充服务提供程序严重依赖自动填充提示。请确保当前使用的自动填充服务支持自动填充提示中的条目(通常可以在移动终端的系统设置中找到服务名称)。
在开发过程中,我们不会自动填充,以便为许多用户提供最适合的解决方案。
但一般来说,为了获得最好的经验:
1.必须将keyboardType定义为准确的预期文本输入。
1.最好只指定一个AutofillHint类型 (所有类型都可以在here中找到),该类型最容易与您的keyboardType或TextInputType对齐,但如果您必须列出多组AutofillHint类型,则应该从与指定的keyboardType最密切相关的类型开始;特别是为了满足iOS设置为seen here的要求
某些自动填充提示仅适用于特定的keyboardType。例如,AutofillHints.name需要TextInputType.name,而AutofillHints.email仅适用于TextInputType. emailAddresss。请确保输入字段具有兼容的keyboardType。根据经验,TextInputType.name适用于iOS上预定义的许多自动填充提示。
所以你可以有
字符串
wf82jlnq2#
我测试了官方flutter bloc示例-登录流。除了他们使用formz库来简化表单验证,它几乎和我的一样。所以我在那里添加了
AutofillGroup
,它工作了。我终于找到了它在我的情况下不工作的原因。这是因为我使用了:字符串
formValidator
在提交时改变(新状态是发出新的表单验证器值),所以它导致整个表单(包括AutofillGroup
)重建。在这种情况下,自动填充似乎会丢失其上下文,并且不再有任何数据要保存。解决方案是删除顶级选择并使用此选项,以确保仅在需要时刷新表单项:
型
除此之外,Flutter的自动填充方法仍然不是很好。如果自动填充服务是Google,它工作得很好,但它几乎从来没有像第三方自动填充服务那样工作。在iOS上,一般来说它不工作。密码可以保存到密钥库,但自动填充对话框不会出现,我需要手动查找凭据。