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

安装
请在此处按照安装说明进行安装 此处
参考
| 属性 | 类型 | 描述 |
|---|---|---|
| onSignup | AuthCallback |
在用户处于注册模式并点击提交按钮时调用 |
| onLogin | AuthCallback |
在用户处于登录模式并点击提交按钮时调用 |
| onRecoverPassword | RecoverCallback |
在用户处于密码恢复模式并点击提交按钮时调用 |
| title | 字符串 |
[Card] 上方的文字,通常是应用或公司名称 |
| logo | 字符串 |
将传递给 Image.asset() 的资源图像路径 |
| messages | LoginMessages |
描述所有标签、文本提示、按钮文本和其他身份验证描述 |
| theme | LoginTheme |
FlutterLogin 的主题。如果未指定,它将使用演示 GIF 中显示的默认主题,并使用最近的 Theme 小部件中的颜色方案 |
| emailValidator | FormFieldValidator<String> |
电子邮件验证逻辑,如果输入无效,则返回要显示的错误字符串,否则返回 null |
| passwordValidator | FormFieldValidator<String> |
与 emailValidator 相同,但用于密码 |
| onSubmitAnimationCompleted | 功能 |
提交动画完成后调用。在此处放置您的路由过渡逻辑 |
| logoTag | 字符串 |
logo 图像的 Hero 标签。如果未指定,则在更改路由时它将简单地淡出 |
| titleTag | 字符串 |
标题文本的 Hero 标签。如果您希望在 Hero 动画前后拥有不同的字体大小,则需要指定 LoginTheme.beforeHeroFontSize 和 LoginTheme.afterHeroFontSize |
| showDebugButtons | 布尔值 |
显示调试按钮以快速前进/后退登录动画。在发布模式下,此选项将覆盖为 false,无论传递的值如何 |
注意: 建议 Hero 小部件的子项应与
两个地方相同。对于标题的 Hero 动画,请使用
下一个屏幕中的 LoginTheme.loginTextStyle 来获取该文本的样式
登录屏幕中的精确文本小部件。LoginTheme 可以通过添加
此行来访问
import 'package:flutter_login/theme.dart';
LoginMessages
| 属性 | 类型 | 描述 |
|---|---|---|
| usernameHint | 字符串 |
用户名 [TextField] 的提示文本 |
| passwordHint | 字符串 |
密码 [TextField] 的提示文本 |
| confirmPasswordHint | 字符串 |
确认密码 [TextField] 的提示文本 |
| forgotPasswordButton | 字符串 |
忘记密码按钮的标签 |
| loginButton | 字符串 |
登录按钮的标签 |
| signupButton | 字符串 |
注册按钮的标签 |
| recoverPasswordButton | 字符串 |
密码恢复按钮的标签 |
| recoverPasswordDescription | 字符串 |
密码恢复表单中的描述 |
| goBackButton | 字符串 |
返回按钮的标签。返回按钮用于从密码恢复表单返回到登录/注册表单 |
| confirmPasswordError | 字符串 |
当确认密码与原始密码不匹配时显示的错误消息 |
| recoverPasswordSuccess | 字符串 |
提交密码恢复后显示的成功消息 |
LoginTheme
| 属性 | 类型 | 描述 |
|---|---|---|
| primaryColor | 颜色 |
小部件主要部分(如登录屏幕和按钮)的背景颜色 |
| accentColor | 颜色 |
次要颜色,用于标题文本颜色、加载图标等。应与 [primaryColor] 对比 |
| errorColor | 颜色 |
[TextField] 输入验证错误的颜色 |
| cardTheme | CardTheme |
用于渲染身份验证 [Card] 的颜色和样式 |
| inputTheme | InputDecorationTheme |
定义所有 [TextField] 的外观 |
| buttonTheme | LoginButtonTheme |
用于自定义提交按钮形状、阴影和颜色的主题 |
| titleStyle | TextStyle |
大标题的文本样式 |
| bodyStyle | TextStyle |
用于小文本(如密码恢复描述)的文本样式 |
| textFieldStyle | TextStyle |
[TextField] 输入文本的文本样式 |
| buttonStyle | TextStyle |
按钮文本的文本样式 |
| beforeHeroFontSize | 双精度 |
定义登录屏幕标题的字体大小(在 Hero 过渡之前) |
| afterHeroFontSize | 双精度 |
定义登录屏幕后的屏幕标题的字体大小(在 Hero 过渡之后) |
示例
您可以在 [示例项目] 中查看完整的示例,该项目产生了上面的
gif 动图
基本示例
import 'package:flutter/material.dart';
import 'package:flutter_login/flutter_login.dart';
import 'dashboard_screen.dart';
const users = const {
'[email protected]': '12345',
'[email protected]': 'hunter',
};
class LoginScreen extends StatelessWidget {
Duration get loginTime => Duration(milliseconds: 2250);
Future<String> _authUser(LoginData data) {
print('Name: ${data.name}, Password: ${data.password}');
return Future.delayed(loginTime).then((_) {
if (!users.containsKey(data.name)) {
return 'Username not exists';
}
if (users[data.name] != data.password) {
return 'Password does not match';
}
return null;
});
}
Future<String> _recoverPassword(String name) {
print('Name: $name');
return Future.delayed(loginTime).then((_) {
if (!users.containsKey(name)) {
return 'Username not exists';
}
return null;
});
}
@override
Widget build(BuildContext context) {
return FlutterLogin(
title: 'ECORP',
logo: 'assets/images/ecorp-lightblue.png',
onLogin: _authUser,
onSignup: _authUser,
onSubmitAnimationCompleted: () {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => DashboardScreen(),
));
},
onRecoverPassword: _recoverPassword,
);
}
}

通过 ThemeData 进行主题化
登录主题可以通过使用 ThemeData 来间接定制,如下所示
// main.dart
import 'package:flutter/material.dart';
import 'login_screen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Login Demo',
theme: ThemeData(
primarySwatch: Colors.deepPurple,
accentColor: Colors.orange,
cursorColor: Colors.orange,
textTheme: TextTheme(
display2: TextStyle(
fontFamily: 'OpenSans',
fontSize: 45.0,
color: Colors.orange,
),
button: TextStyle(
fontFamily: 'OpenSans',
),
subhead: TextStyle(fontFamily: 'NotoSans'),
body1: TextStyle(fontFamily: 'NotoSans'),
),
),
home: LoginScreen(),
);
}
}
// login_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_login/flutter_login.dart';
import 'dashboard_screen.dart';
class LoginScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FlutterLogin(
title: 'ECORP',
logo: '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
Widget build(BuildContext context) {
return FlutterLogin(
title: 'ECORP',
logo: 'assets/images/ecorp.png',
onLogin: (_) => Future(null),
onSignup: (_) => Future(null),
onSubmitAnimationCompleted: () {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => DashboardScreen(),
));
},
onRecoverPassword: (_) => Future(null),
messages: LoginMessages(
usernameHint: 'Username',
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
Widget build(BuildContext context) {
final inputBorder = BorderRadius.vertical(
bottom: Radius.circular(10.0),
top: Radius.circular(20.0),
);
return FlutterLogin(
title: 'ECORP',
logo: '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),
),
// shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
// shape: CircleBorder(side: BorderSide(color: Colors.green)),
// shape: ContinuousRectangleBorder(borderRadius: BorderRadius.circular(55.0)),
),
),
);
}
}


