首页 > 解决方案 > 如何使用键盘完成按钮 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,
            );
          },
        );
      }
    }

标签: flutterdartstreamrxdart

解决方案


您可以使用另一个 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,
          );
        });
     });
  }

推荐阅读