Flutter动画登录界面插件animated_login的使用
Flutter动画登录界面插件animated_login的使用
概述
Animated Login
是一个为Flutter准备的现成的登录/注册屏幕,带有柔和且令人愉悦的动画。它完全响应式设计,可以在Web和移动端应用中使用。你可以用这个美丽的动画屏幕迎接用户,并提供登录和注册功能。
作者
示例视频
Web端示例
移动端示例
安装
安装说明请参考 这里
配置隐私政策链接 - URL launcher
iOS
在 Info.plist
文件中添加URL方案:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>sms</string>
<string>tel</string>
</array>
Android
在 AndroidManifest.xml
文件中添加URL方案:
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="sms" />
</intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="tel" />
</intent>
</queries>
参考文档
属性列表
Property | Type | Description |
---|---|---|
onSignup | SignupCallback |
注册按钮点击后的回调 |
onLogin | LoginCallback |
登录按钮点击后的回调 |
socialLogins | List<SocialLogin> |
社交登录选项 |
loginTexts | LoginTexts |
界面上所有文本的定义 |
loginDesktopTheme | LoginViewTheme |
桌面视图的主题设置 |
loginMobileTheme | LoginViewTheme |
移动端视图的主题设置 |
onForgotPassword | ForgotPasswordCallback |
忘记密码点击后的回调 |
formKey | GlobalKey<FormState> |
自定义表单键(可选) |
checkError | bool |
是否处理错误并显示错误信息 |
showForgotPassword | bool |
是否启用忘记密码选项 |
showChangeActionTitle | bool |
是否显示切换动作标题 |
showPasswordVisibility | bool |
是否允许用户显示密码文本 |
nameValidator | ValidatorModel |
名称字段的自定义验证器 |
emailValidator | ValidatorModel |
邮箱字段的自定义验证器 |
passwordValidator | ValidatorModel |
密码字段的自定义验证器 |
validateName | bool |
是否验证名称字段 |
validateEmail | bool |
是否验证邮箱字段 |
validatePassword | bool |
是否验证密码字段 |
nameController | TextEditingController |
名称输入字段的控制器(可选) |
emailController | TextEditingController |
邮箱输入字段的控制器(可选) |
passwordController | TextEditingController |
密码输入字段的控制器(可选) |
confirmPasswordController | TextEditingController |
确认密码输入字段的控制器(可选) |
backgroundImage | String |
欢迎部分背景图片的完整资产路径 |
logo | Widget |
显示logo的自定义小部件 |
signUpMode | SignUpModes |
确定应显示哪些文本字段:名称 / 确认密码 / 两者 |
languageOptions | List<LanguageOption> |
用户可以选择的语言列表 |
changeLanguageCallback | ChangeLanguageCallback |
语言选择后的回调 |
selectedLanguage | LanguageOption |
已存储的选定语言 |
changeLangOnPressed | ChangeLangOnPressedCallback |
点击更改语言按钮时调用的函数 |
完整示例代码
import 'package:animated_login/animated_login.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Animated Login',
theme: ThemeData(
primaryColor: Colors.blue,
colorScheme: const ColorScheme.light(primary: Colors.blue),
textTheme: Theme.of(context).textTheme.apply(decorationColor: Colors.blue),
inputDecorationTheme: const InputDecorationTheme(
prefixIconColor: Colors.black54,
suffixIconColor: Colors.black54,
iconColor: Colors.black54,
labelStyle: TextStyle(color: Colors.black54),
hintStyle: TextStyle(color: Colors.black54),
),
),
debugShowCheckedModeBanner: false,
initialRoute: '/login',
routes: {
'/login': (BuildContext context) => const LoginScreen(),
'/forgotPass': (BuildContext context) => const ForgotPasswordScreen(),
},
);
}
}
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
LanguageOption language = _languageOptions[1];
AuthMode currentMode = AuthMode.login;
CancelableOperation? _operation;
@override
Widget build(BuildContext context) {
return AnimatedLogin(
onLogin: (LoginData data) async => _authOperation(LoginFunctions(context).onLogin(data)),
onSignup: (SignUpData data) async => _authOperation(LoginFunctions(context).onSignup(data)),
onForgotPassword: _onForgotPassword,
logo: Image.asset('assets/images/logo.gif'),
signUpMode: SignUpModes.both,
socialLogins: _socialLogins(context),
loginDesktopTheme: _desktopTheme,
loginMobileTheme: _mobileTheme,
loginTexts: _loginTexts,
emailValidator: ValidatorModel(
validatorCallback: (String? email) => 'What an email! $email'),
changeLanguageCallback: (LanguageOption? _language) {
if (_language != null) {
DialogBuilder(context).showResultDialog(
'Successfully changed the language to: ${_language.value}.');
if (mounted) setState(() => language = _language);
}
},
changeLangDefaultOnPressed: () async => _operation?.cancel(),
languageOptions: _languageOptions,
selectedLanguage: language,
initialMode: currentMode,
onAuthModeChange: (AuthMode newMode) async {
currentMode = newMode;
await _operation?.cancel();
},
);
}
Future<String?> _authOperation(Future<String?> func) async {
await _operation?.cancel();
_operation = CancelableOperation.fromFuture(func);
final String? res = await _operation?.valueOrCancellation();
if (_operation?.isCompleted == true) {
DialogBuilder(context).showResultDialog(res ?? 'Successful.');
}
return res;
}
Future<String?> _onForgotPassword(String email) async {
await _operation?.cancel();
return await LoginFunctions(context).onForgotPassword(email);
}
static List<LanguageOption> get _languageOptions => const <LanguageOption>[
LanguageOption(
value: 'Turkish',
code: 'TR',
iconPath: 'assets/images/tr.png',
),
LanguageOption(
value: 'English',
code: 'EN',
iconPath: 'assets/images/en.png',
),
];
LoginViewTheme get _desktopTheme => _mobileTheme.copyWith(
actionButtonStyle: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.white),
),
dialogTheme: const AnimatedDialogTheme(
languageDialogTheme: LanguageDialogTheme(optionMargin: EdgeInsets.symmetric(horizontal: 80)),
),
loadingSocialButtonColor: Colors.blue,
loadingButtonColor: Colors.white,
privacyPolicyStyle: const TextStyle(color: Colors.black87),
privacyPolicyLinkStyle: const TextStyle(color: Colors.blue, decoration: TextDecoration.underline),
);
LoginViewTheme get _mobileTheme => LoginViewTheme(
backgroundColor: Colors.blue,
formFieldBackgroundColor: Colors.white,
formWidthRatio: 60,
actionButtonStyle: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.blue),
),
animatedComponentOrder: const <AnimatedComponent>[
AnimatedComponent(component: LoginComponents.logo, animationType: AnimationType.right),
AnimatedComponent(component: LoginComponents.title),
AnimatedComponent(component: LoginComponents.description),
AnimatedComponent(component: LoginComponents.formTitle),
AnimatedComponent(component: LoginComponents.socialLogins),
AnimatedComponent(component: LoginComponents.useEmail),
AnimatedComponent(component: LoginComponents.form),
AnimatedComponent(component: LoginComponents.notHaveAnAccount),
AnimatedComponent(component: LoginComponents.forgotPassword),
AnimatedComponent(component: LoginComponents.policyCheckbox),
AnimatedComponent(component: LoginComponents.changeActionButton),
AnimatedComponent(component: LoginComponents.actionButton),
],
privacyPolicyStyle: const TextStyle(color: Colors.white70),
privacyPolicyLinkStyle: const TextStyle(color: Colors.white, decoration: TextDecoration.underline),
);
LoginTexts get _loginTexts => LoginTexts(
nameHint: _username,
login: _login,
signUp: _signup,
);
String get _username => language.code == 'TR' ? 'Kullanıcı Adı' : 'Username';
String get _login => language.code == 'TR' ? 'Giriş Yap' : 'Login';
String get _signup => language.code == 'TR' ? 'Kayıt Ol' : 'Sign Up';
List<SocialLogin> _socialLogins(BuildContext context) => <SocialLogin>[
SocialLogin(callback: () async => _socialCallback('Google'), iconPath: 'assets/images/google.png'),
SocialLogin(callback: () async => _socialCallback('Facebook'), iconPath: 'assets/images/facebook.png'),
SocialLogin(callback: () async => _socialCallback('LinkedIn'), iconPath: 'assets/images/linkedin.png'),
];
Future<String?> _socialCallback(String type) async {
await _operation?.cancel();
_operation = CancelableOperation.fromFuture(LoginFunctions(context).socialLogin(type));
final String? res = await _operation?.valueOrCancellation();
if (_operation?.isCompleted == true && res == null) {
DialogBuilder(context).showResultDialog('Successfully logged in with $type.');
}
return res;
}
}
class ForgotPasswordScreen extends StatelessWidget {
const ForgotPasswordScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('FORGOT PASSWORD'),
),
);
}
}
更多截图
Web 登录 | 移动端 登录 |
---|---|
![]() |
![]() |
Web 注册 | 移动端 注册 |
---|---|
![]() |
![]() |
颜色变化 | 无社交登录 |
---|---|
![]() |
![]() |
错误示例 |
---|
![]() |
贡献
贡献对于本项目非常重要。如果你有时间推动包的发展,我将非常感激。有关问题、错误报告、问题、功能请求、拉取请求等,请先参阅 贡献指南。
如果你喜欢并受益于这个包,请在GitHub上给我们 加星,并在pub.dev上 点赞以帮助我们!
许可证
MIT License
更多关于Flutter动画登录界面插件animated_login的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter动画登录界面插件animated_login的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个使用 animated_login
插件创建 Flutter 动画登录界面的示例代码。这个插件可以帮助你快速实现一个带有动画效果的登录界面。
首先,确保你已经在 pubspec.yaml
文件中添加了 animated_login
依赖:
dependencies:
flutter:
sdk: flutter
animated_login: ^x.y.z # 请替换为最新版本号
然后,运行 flutter pub get
来获取依赖。
接下来是示例代码,展示如何使用 animated_login
插件:
import 'package:flutter/material.dart';
import 'package:animated_login/animated_login.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Animated Login Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AnimatedLoginScreen(),
);
}
}
class AnimatedLoginScreen extends StatefulWidget {
@override
_AnimatedLoginScreenState createState() => _AnimatedLoginScreenState();
}
class _AnimatedLoginScreenState extends State<AnimatedLoginScreen> {
final _formKey = GlobalKey<FormState>();
String _email = '';
String _password = '';
void _submit() {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
// 在这里处理登录逻辑,比如发送到服务器
print('Email: $_email');
print('Password: $_password');
// 假设登录成功,显示一个简单的Snackbar
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('登录成功!')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Animated Login Demo'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: AnimatedLogin(
title: '登录',
subTitle: '请输入您的信息',
image: Image.asset('assets/logo.png'), // 替换为你的图片资源
form: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty || !value.contains('@')) {
return '请输入有效的电子邮件地址';
}
return null;
},
onSaved: (value) {
_email = value!;
},
),
SizedBox(height: 16),
TextFormField(
decoration: InputDecoration(labelText: '密码'),
validator: (value) {
if (value == null || value.isEmpty || value.length < 6) {
return '密码至少6个字符';
}
return null;
},
obscureText: true,
onSaved: (value) {
_password = value!;
},
),
SizedBox(height: 24),
AnimatedLoginButton(
onPressed: _submit,
child: Text('登录'),
),
],
),
),
),
),
);
}
}
注意事项
- 图片资源:确保在
assets
文件夹中有logo.png
或替换为你自己的图片资源,并在pubspec.yaml
中声明该资源。 - 依赖版本:确保
animated_login
插件的版本号是最新的,以避免兼容性问题。 - 表单验证:示例中包含了基本的表单验证逻辑,你可以根据需求进一步扩展。
这个示例展示了如何使用 animated_login
插件创建一个带有动画效果的登录界面,并包含基本的表单验证和登录提交逻辑。希望这对你有所帮助!