Flutter登录功能优化插件flutter_login_fix的使用

Flutter 登录功能优化插件 flutter_login_fix 的使用

flutter_login 是一个现成的登录/注册小部件,具有许多动画效果来展示 Flutter 的能力。

安装

请按照以下步骤安装 flutter_login

dependencies:
  flutter_login:

参考文档

属性表

属性名 类型 描述
onSignup AuthCallback 当用户在注册模式下点击提交按钮时调用。接收一个包含用户名、密码及任何其他字段的 SignupData 对象。
onConfirmSignup ConfirmSignupCallback 当用户点击确认注册时调用。如果未指定,则注册不会被用户确认。
confirmSignupRequired ConfirmSignupRequiredCallback 动态决定是否需要确认。如果未指定,且 onConfirmSignup 指定,则会由用户确认。
confirmSignupKeyboardType TextInputType 确认注册字段的键盘类型。
onResendCode AuthCallback 当用户点击重新发送代码按钮时调用。仅在提供了 onConfirmSignup 时才需要。
onLogin AuthCallback 当用户在登录模式下点击提交按钮时调用。
onRecoverPassword RecoverCallback 当用户点击提交按钮进行密码恢复时调用。
onConfirmRecover ConfirmRecoverCallback 当用户在密码恢复模式下提交确认码并设置新密码时调用。如果未指定,将不使用确认码来恢复密码。
title String 登录屏幕上方的大文本,通常为应用或公司名称。留空或为 null 则无标题。
logo ImageProviderString 用于显示的 logo 图像的图像提供者或资源路径字符串。
messages LoginMessages 描述所有标签、文本提示、按钮文本和其他身份验证描述。
theme LoginTheme FlutterLogin 的主题。如果没有指定,将使用默认主题,并使用最近的 Theme 小部件的颜色方案。
userType LoginUserType FlutterLogin 的用户类型。如果没有指定,默认使用电子邮件作为用户类型。
userValidator FormFieldValidator<String> 用户字段验证逻辑。在此添加自定义验证。默认为电子邮件验证逻辑。期望返回一个错误消息字符串(显示)或 null(验证成功)。
validateUserImmediately bool 是否在失去焦点后验证电子邮件(true)或在表单提交后验证(false)。默认为 false
passwordValidator FormFieldValidator<String> userValidator 类似,但针对密码。
onSubmitAnimationCompleted Function 在提交动画完成后调用。在此放置路由过渡逻辑。
logoTag String Hero 标签用于 logo 图像。如果没有指定,它将在更改路由时淡出。
titleTag String Hero 标签用于标题文本。如果想要不同的字体大小在英雄动画之前和之后,请指定 LoginTheme.beforeHeroFontSizeLoginTheme.afterHeroFontSize
showDebugButtons bool 显示调试按钮以快速前进/后退登录动画。在发布模式下,此值将被覆盖为 false 无论传入的值是什么。
hideForgotPasswordButton bool 如果设置为 true,则隐藏忘记密码按钮。
hideProvidersTitle bool 如果设置为 true,则隐藏登录提供者上方的标题。如果提供者列表为空,则此选项无效,因为标题将被隐藏。默认为 false
disableCustomPageTransformer bool 禁用可能导致 RenderBox was not laid out 错误的自定义过渡。更多信息请参见 #97
additionalSignUpFields Map<String, UserFormField> 用于指定额外的表单字段;表单在注册后立即显示。最多可以提供 6 个额外字段。
onSwitchToAdditionalFields AdditionalFieldsCallback 当用户切换到附加字段时调用。
navigateBackAfterRecovery bool 成功恢复密码后导航回登录页面。
savedEmail String 预填的用户字段值(即通过其他方式从以前的会话中保存的值,例如通过 SharedPreferences)。
savedPassword String 预填的密码字段值(即通过其他方式从以前的会话中保存的值,例如通过 SharedPreferences)。 也会设置 Auth 类中的确认密码。
termsOfService TermOfService 注册期间列出的一系列服务条款。在 onSignup 回调 LoginData 中包含一个 TermOfServiceResult 列表。
children [Widget] 可以添加到登录屏幕堆栈中的小部件列表。可以用来显示自定义横幅或徽标。
scrollable bool 设置为 true 时,登录卡片变为可滚动而不是根据需要调整大小。
headerWidget Widget 可以放置在登录卡片顶部的小部件。

示例代码

基本示例

import 'package:flutter/material.dart';
import 'package:flutter_login/flutter_login.dart';
import 'dashboard_screen.dart';

const users = const {
  'dribbble@gmail.com': '12345',
  'hunter@gmail.com': 'hunter',
};

class LoginScreen extends StatelessWidget {
  Duration get loginTime => Duration(milliseconds: 2250);

  Future<String?> _authUser(LoginData data) {
    debugPrint('Name: ${data.name}, Password: ${data.password}');
    return Future.delayed(loginTime).then((_) {
      if (!users.containsKey(data.name)) {
        return 'User not exists';
      }
      if (users[data.name] != data.password) {
        return 'Password does not match';
      }
      return null;
    });
  }

  Future<String?> _signupUser(SignupData data) {
    debugPrint('Signup Name: ${data.name}, Password: ${data.password}');
    return Future.delayed(loginTime).then((_) {
      return null;
    });
  }

  Future<String> _recoverPassword(String name) {
    debugPrint('Name: $name');
    return Future.delayed(loginTime).then((_) {
      if (!users.containsKey(name)) {
        return 'User not exists';
      }
      return null;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FlutterLogin(
      title: 'ECORP',
      logo: AssetImage('assets/images/ecorp-lightblue.png'),
      onLogin: _authUser,
      onSignup: _signupUser,
      onSubmitAnimationCompleted: () {
        Navigator.of(context).pushReplacement(MaterialPageRoute(
          builder: (context) => DashboardScreen(),
        ));
      },
      onRecoverPassword: _recoverPassword,
    );
  }
}

带有登录提供者的示例

import 'package:flutter/material.dart';
import 'package:flutter_login/flutter_login.dart';
import 'dashboard_screen.dart';

const users = const {
  'dribbble@gmail.com': '12345',
  'hunter@gmail.com': 'hunter',
};

class LoginScreen extends StatelessWidget {
  Duration get loginTime => Duration(milliseconds: 2250);

  Future<String?> _authUser(LoginData data) {
    debugPrint('Name: ${data.name}, Password: ${data.password}');
    return Future.delayed(loginTime).then((_) {
      if (!users.containsKey(data.name)) {
        return 'User not exists';
      }
      if (users[data.name] != data.password) {
        return 'Password does not match';
      }
      return null;
    });
  }

  Future<String?> _signupUser(SignupData data) {
    debugPrint('Signup Name: ${data.name}, Password: ${data.password}');
    return Future.delayed(loginTime).then((_) {
      return null;
    });
  }

  Future<String> _recoverPassword(String name) {
    debugPrint('Name: $name');
    return Future.delayed(loginTime).then((_) {
      if (!users.containsKey(name)) {
        return 'User not exists';
      }
      return null;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FlutterLogin(
      title: 'ECORP',
      logo: AssetImage('assets/images/ecorp-lightblue.png'),
      onLogin: _authUser,
      onSignup: _signupUser,
      loginProviders: [
        LoginProvider(
          icon: FontAwesomeIcons.google,
          label: 'Google',
          callback: () async {
            debugPrint('start google sign in');
            await Future.delayed(loginTime);
            debugPrint('stop google sign in');              
            return null;
          },
        ),
        LoginProvider(
          icon: FontAwesomeIcons.facebookF,
          label: 'Facebook',
          callback: () async {            
            debugPrint('start facebook sign in');
            await Future.delayed(loginTime);
            debugPrint('stop facebook sign in');              
            return null;
          },
        ),
        LoginProvider(
          icon: FontAwesomeIcons.linkedinIn,
          callback: () async {         
            debugPrint('start linkdin sign in');
            await Future.delayed(loginTime);         
            debugPrint('stop linkdin sign in');              
            return null;
          },
        ),
        LoginProvider(
          icon: FontAwesomeIcons.githubAlt,
          callback: () async {
            debugPrint('start github sign in');
            await Future.delayed(loginTime);
            debugPrint('stop github sign in');              
            return null;
          },
        ),
      ],
      onSubmitAnimationCompleted: () {
        Navigator.of(context).pushReplacement(MaterialPageRoute(
          builder: (context) => DashboardScreen(),
        ));
      },
      onRecoverPassword: _recoverPassword,
    );
  }
}

使用 ThemeData 进行主题定制

import 'package:flutter/material.dart';
import 'package:flutter_login/flutter_login.dart';
import 'dashboard_screen.dart';

class LoginScreen extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return FlutterLogin(
      title: 'ECORP',
      logo: AssetImage('assets/images/ecorp.png'),
      onLogin: (_) => Future(null),
      onSignup: (_) => Future(null),
      onSubmitAnimationCompleted: () {
        Navigator.of(context).pushReplacement(MaterialPageRoute(
          builder: (context) => DashboardScreen(),
        ));
      },
      onRecoverPassword: (_) => Future(null),
    );
  }
}

自定义标签

import 'package:flutter/material.dart';
import 'package:flutter_login/flutter_login.dart';
import 'dashboard_screen.dart';

class LoginScreen extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return FlutterLogin(
      title: 'ECORP',
      logo: AssetImage('assets/images/ecorp.png'),
      onLogin: (_) => Future(null),
      onSignup: (_) => Future(null),
      onSubmitAnimationCompleted: () {
        Navigator.of(context).pushReplacement(MaterialPageRoute(
          builder: (context) => DashboardScreen(),
        ));
      },
      onRecoverPassword: (_) => Future(null),
      messages: LoginMessages(
        userHint: 'User',
        passwordHint: 'Pass',
        confirmPasswordHint: 'Confirm',
        loginButton: 'LOG IN',
        signupButton: 'REGISTER',
        forgotPasswordButton: 'Forgot huh?',
        recoverPasswordButton: 'HELP ME',
        goBackButton: 'GO BACK',
        confirmPasswordError: 'Not match!',
        recoverPasswordDescription:
            'Lorem Ipsum is simply dummy text of the printing and typesetting industry',
        recoverPasswordSuccess: 'Password rescued successfully',
      ),
    );
  }
}

主题定制

import 'package:flutter/material.dart';
import 'package:flutter_login/flutter_login.dart';
import 'dashboard_screen.dart';

class LoginScreen extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    final inputBorder = BorderRadius.vertical(
      bottom: Radius.circular(10.0),
      top: Radius.circular(20.0),
    );

    return FlutterLogin(
      title: 'ECORP',
      logo: AssetImage('assets/images/ecorp-lightgreen.png'),
      onLogin: (_) => Future(null),
      onSignup: (_) => Future(null),
      onSubmitAnimationCompleted: () {
        Navigator.of(context).pushReplacement(MaterialPageRoute(
          builder: (context) => DashboardScreen(),
        ));
      },
      onRecoverPassword: (_) => Future(null),
      theme: LoginTheme(
        primaryColor: Colors.teal,
        accentColor: Colors.yellow,
        errorColor: Colors.deepOrange,
        titleStyle: TextStyle(
          color: Colors.greenAccent,
          fontFamily: 'Quicksand',
          letterSpacing: 4,
        ),
        bodyStyle: TextStyle(
          fontStyle: FontStyle.italic,
          decoration: TextDecoration.underline,
        ),
        textFieldStyle: TextStyle(
          color: Colors.orange,
          shadows: [Shadow(color: Colors.yellow, blurRadius: 2)],
        ),
        buttonStyle: TextStyle(
          fontWeight: FontWeight.w800,
          color: Colors.yellow,
        ),
        cardTheme: CardTheme(
          color: Colors.yellow.shade100,
          elevation: 5,
          margin: EdgeInsets.only(top: 15),
          shape: ContinuousRectangleBorder(
              borderRadius: BorderRadius.circular(100.0)),
        ),
        inputTheme: InputDecorationTheme(
          filled: true,
          fillColor: Colors.purple.withOpacity(.1),
          contentPadding: EdgeInsets.zero,
          errorStyle: TextStyle(
            backgroundColor: Colors.orange,
            color: Colors.white,
          ),
          labelStyle: TextStyle(fontSize: 12),
          enabledBorder: UnderlineInputBorder(
            borderSide: BorderSide(color: Colors.blue.shade700, width: 4),
            borderRadius: inputBorder,
          ),
          focusedBorder: UnderlineInputBorder(
            borderSide: BorderSide(color: Colors.blue.shade400, width: 5),
            borderRadius: inputBorder,
          ),
          errorBorder: UnderlineInputBorder(
            borderSide: BorderSide(color: Colors.red.shade700, width: 7),
            borderRadius: inputBorder,
          ),
          focusedErrorBorder: UnderlineInputBorder(
            borderSide: BorderSide(color: Colors.red.shade400, width: 8),
            borderRadius: inputBorder,
          ),
          disabledBorder: UnderlineInputBorder(
            borderSide: BorderSide(color: Colors.grey, width: 5),
            borderRadius: inputBorder,
          ),
        ),
        buttonTheme: LoginButtonTheme(
          splashColor: Colors.purple,
          backgroundColor: Colors.pinkAccent,
          highlightColor: Colors.lightGreen,
          elevation: 9.0,
          highlightElevation: 6.0,
          shape: BeveledRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter登录功能优化插件flutter_login_fix的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter登录功能优化插件flutter_login_fix的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,flutter_login_fix 并不是一个广泛认知的 Flutter 插件,但基于你的要求,我将假设这是一个假想的插件,旨在优化 Flutter 应用中的登录功能。在实际开发中,优化登录功能可能涉及表单验证、错误处理、用户体验增强等多个方面。

以下是一个使用 Flutter 和一些常见插件(如 form_field_validator 用于表单验证)来实现优化登录功能的示例代码。虽然这不是直接使用 flutter_login_fix,但它展示了如何实现类似的优化效果。

1. 添加依赖

首先,在 pubspec.yaml 文件中添加必要的依赖:

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.0
  form_field_validator: ^2.0.0

2. 创建登录表单

接下来,创建一个登录表单,包括用户名和密码字段,以及登录按钮。使用 form_field_validator 进行表单验证。

import 'package:flutter/material.dart';
import 'package:form_field_validator/form_field_validator.dart';
import 'package:provider/provider.dart';

class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  final _formKey = GlobalKey<FormState>();
  String _email = '';
  String _password = '';
  String _errorMessage = '';

  void _submit() {
    if (_formKey.currentState!.validate()) {
      _formKey.currentState!.save();
      // 在这里添加登录逻辑,比如调用API
      _performLogin();
    }
  }

  Future<void> _performLogin() async {
    // 模拟API调用
    await Future.delayed(Duration(seconds: 2));

    // 假设验证成功
    setState(() {
      _errorMessage = '';
      // 这里可以导航到主屏幕或其他页面
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('登录'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: <Widget>[
              TextFormField(
                decoration: InputDecoration(labelText: '邮箱'),
                validator: MultiValidator([
                  RequiredValidator(errorText: '邮箱是必填项'),
                  EmailValidator(errorText: '请输入有效的邮箱地址'),
                ]),
                onSaved: (value) {
                  _email = value!;
                },
              ),
              TextFormField(
                decoration: InputDecoration(labelText: '密码'),
                validator: MultiValidator([
                  RequiredValidator(errorText: '密码是必填项'),
                  MinLengthValidator(6, errorText: '密码长度不能少于6个字符'),
                ]),
                obscureText: true,
                onSaved: (value) {
                  _password = value!;
                },
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: _submit,
                child: Text('登录'),
              ),
              SizedBox(height: 10),
              Text(
                _errorMessage,
                style: TextStyle(color: Colors.red),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

3. 使用 Provider 管理状态(可选)

如果需要在应用的不同部分共享登录状态(例如用户信息),可以使用 provider 包来管理状态。

class UserProvider with ChangeNotifier {
  User? _user;

  User? get user => _user;

  void logIn(String email, String password) {
    // 在这里添加实际的登录逻辑,比如调用API
    // 假设验证成功,设置用户信息
    _user = User(email: email, password: password); // 注意:不要在实际应用中存储密码
    notifyListeners();
  }

  void logOut() {
    _user = null;
    notifyListeners();
  }
}

class User {
  final String email;
  final String password; // 仅用于示例,实际中不应存储密码

  User({required this.email, required this.password});
}

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => UserProvider()),
      ],
      child: MyApp(),
    ),
  );
}

MyApp 中,你可以根据用户登录状态来显示不同的界面,比如登录页面或主屏幕。

总结

虽然我们没有直接使用 flutter_login_fix 插件,但上面的代码展示了如何使用 Flutter 和一些常见插件来实现一个优化过的登录功能,包括表单验证、错误处理和状态管理。这些都是优化登录体验的关键要素。如果你有一个具体的 flutter_login_fix 插件,并且需要更具体的帮助,请提供更多关于该插件的信息。

回到顶部