flutter - 如何使用键盘完成按钮 Flutter、observable、streamBuilder 实现验证
问题描述
我正在使用类似 Flutter 和 Bloc 的架构构建应用程序。我正在尝试使用登录按钮以及带有密码的键盘完成按钮来调用提交函数;仅当电子邮件和密码有效时。
我可以使用 combineLatest 实现登录按钮版本,但我不确定键盘版本。在调用提交之前按下键盘完成按钮时,我需要验证电子邮件和密码。我可以嵌套streamBuilder,但我觉得这不是一个好习惯。
有什么方法可以从 combineLatest 中获取最新值?BehaviorSubject<bool>().value
或任何可能的建议来实现这一点。
示例代码:
final _emailController = BehaviorSubject<String>();
final _passwordController = BehaviorSubject<String>();
// Add data to stream
Stream<String> get email => _emailController.stream.transform(validateEmail);
Stream<String> get password =>
_passwordController.stream.transform(validatePassword);
Stream<bool> get submitValid =>
Observable.combineLatest2(email, password, (e, p) => true);
// change data
Function(String) get changeEmail => _emailController.sink.add;
Function(String) get changePassword => _passwordController.sink.add;
submit() {
final validEmail = _emailController.value;
final validPassword = _passwordController.value;
print('Email is $validEmail, and password is $validPassword');
}
import 'package:flutter/material.dart';
import '../blocs/bloc.dart';
import '../blocs/provider.dart';
class LoginScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final bloc = Provider.of(context);
return Container(
margin: EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
emailField(bloc),
passwordField(bloc),
Container(
margin: EdgeInsets.only(top: 25.0),
),
submitButton(bloc),
],
),
);
}
Widget emailField(Bloc bloc) {
return StreamBuilder(
stream: bloc.email,
builder: (context, snapshot) {
return TextField(
onChanged: bloc.changeEmail,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'ypu@example.com',
labelText: 'Email Address',
errorText: snapshot.error,
),
);
},
);
}
Widget passwordField(Bloc bloc) {
return StreamBuilder(
stream: bloc.password,
builder: (context, snapshot) {
return TextField(
obscureText: true,
onChanged: bloc.changePassword,
decoration: InputDecoration(
hintText: 'Password',
labelText: 'Password',
errorText: snapshot.error,
),
textInputAction: TextInputAction.done,
onSubmitted: () {}, // <- here
);
});
}
Widget submitButton(Bloc bloc) {
return StreamBuilder(
stream: bloc.submitValid,
builder: (context, snapshot) {
return RaisedButton(
child: Text('Login'),
color: Colors.blue,
onPressed: snapshot.hasData ? bloc.submit : null,
);
},
);
}
}
解决方案
您可以使用另一个 streamBilder 和 onSubmitted 调用提交方法来包装您的密码 streamBuilder。
Widget passwordField(Bloc bloc) {
return StreamBuilder(
stream: bloc.submitValid,
builder: (context, snap) {
return StreamBuilder(
stream: bloc.password,
builder: (context, snapshot) {
return TextField(
obscureText: true,
onChanged: bloc.changePassword,
decoration: InputDecoration(
hintText: 'Password',
labelText: 'Password',
errorText: snapshot.error,
),
textInputAction: TextInputAction.done,
onSubmitted: snap.hasData ? bloc.submit : null,
);
});
});
}
推荐阅读
- elasticsearch - 如何知道用户是否是使用 elasticsearch 和 redis 的朋友?
- php - Laravel 回调函数控制器不起作用
- spring-cloud-dataflow - 如何使用 OAuth2 连接 Spring Cloud Data Cloud 和 ADFS 服务器
- ios - 在IOS中使用struct decodable swift 4/5解码不同数据类型的json数组数据
- laravel - 验证似乎不适用于我的 laravel 项目
- javascript - 从对象中的条目动态生成 Gulp 4 任务
- javascript - 在 Angular 8 中保存安全信息的最佳位置
- c# - Blazor.net 不需要的按钮单击输入按键
- java - 使用 Robolectric 对 Toast 消息内容进行单元测试
- angular - 当 Ionic 3 中的 Firestore 集合发生更改时,如何实现应用程序范围的通知功能?