效果
Screen_Recording_20240402-145821 (2).gif介绍
在Flutter应用程序中创建登录页面对于用户认证和参与至关重要。登录页面作为用户访问应用程序功能的入口。它应该提供无缝的体验,同时确保安全和隐私。这里仿Boss应用设计的登录页面,我们将创建一个登录页面,允许用户使用手机号码登录或注册。
小插曲
首先,让我们设置Flutter项目并创建一个登录页面组件。我们将使用GetX进行状态管理和UI更新。确保您在开发环境中安装了Flutter和GetX。
实现
1. 依赖项
确保您在pubspec.yaml
文件中具有必要的依赖项:
dependencies:
flutter:
sdk: flutter
get: ^4.6.2
2. 登录页小部件
创建一个名为login_page.dart
的新文件,并定义LoginPage
小部件。此小部件将包含登录页面的UI元素:
// login_page.dart
class LoginPage extends StatelessWidget {
const LoginPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final logic = Get.find<LoginLogic>();
return Scaffold(
body: Container(
padding: EdgeInsets.fromLTRB(24.w, 60.w, 24.w, 24.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"手机号登录/注册",
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 30.sp,
color: RC.text1Color,
),
),
SizedBox(height: 6.w),
Text(
"首次验证通过即注册BOSS直聘账号",
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 14.sp,
color: RC.text2Color,
),
),
SizedBox(height: 10.w),
Row(
children: [
Text(
"+86",
style: TextStyle(
fontSize: 16.sp,
color: Colors.black,
),
),
Icon(
Icons.keyboard_arrow_down,
size: 25.w,
color: Colors.black.withAlpha(70),
),
Expanded(
child: TextField(
controller: logic.controller,
keyboardType: TextInputType.phone,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
],
style: TextStyle(color: Colors.black, fontSize: 18.sp),
onChanged: (value) {
logic.state.phoneNum.value = value;
},
decoration: InputDecoration(
hintText: '请输入您的手机号码',
// 设置 hintText
hintStyle: TextStyle(color: Colors.grey, fontSize: 18.sp),
// 设置 hintText 的颜色
border: InputBorder.none,
// 取消底部下划线
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent), // 取消输入框选中时的边框颜色
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent), // 取消输入框获取焦点时的边框颜色
),
),
),
),
],
),
Divider(
height: 1.w,
color: Colors.grey,
),
SizedBox(height: 16.w),
Obx(
() => InkWell(
onTap: () {
logic.state.isAgree.value = !logic.state.isAgree.value;
},
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(top: 5),
child: Icon(
logic.state.isAgree.value
? Icons.check_circle
: Icons.circle_outlined,
size: 18.r,
color: logic.state.isAgree.value
? RC.themeColor
: Colors.grey,
),
),
SizedBox(width: 5.w),
Expanded(
child:
RichText(
text: TextSpan(
text: '已阅读并同意',
style: const TextStyle(
color: Colors.black, fontSize: 16),
children: [
TextSpan(
text: '《BOSS直聘用户协议》',
style: const TextStyle(color: RC.themeColor),
recognizer: TapGestureRecognizer()
..onTap = () {
ToastUtil.show(msg: "跳转到BOSS直聘用户协议");
},
),
const TextSpan(
text: ' 和 ',
style:
TextStyle(color: Colors.black, fontSize: 16),
),
TextSpan(
text: '《隐私政策》',
style: const TextStyle(color: RC.themeColor),
recognizer: TapGestureRecognizer()
..onTap = () {
ToastUtil.show(msg: "跳转到隐私政策");
},
),
const TextSpan(
text: ',允许BOSS直聘统一管理本人账号信息',
style:
TextStyle(color: Colors.black, fontSize: 16),
),
],
),
),
),
],
),
),
),
Obx(
() => InkWell(
onTap: () {
logic.next(context);
},
child: Container(
height: 50.w,
alignment: Alignment.center,
margin: EdgeInsets.only(top: 20.w, bottom: 30.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(8.r)),
color: logic.state.phoneNum.isNotEmpty
? RC.themeColor
: RC.themeColor.withAlpha(50)),
child: Text(
"下一步",
style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
),
),
Text(
"接受不到短信",
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey,
),
),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
"或通过以下方式登录",
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey,
),
),
SizedBox(height: 20.w),
InkWell(
onTap: () {
logic.wxLogin();
},
child: Image.asset(
R.login_wx_png,
width: 50.w,
height: 50.w,
),
),
SizedBox(height: 35.w),
Text(
"服务热线 举报监督电话 资质证照",
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey,
),
),
],
),
),
),
],
),
),
);
}
}
3. 登录页逻辑
为登录页面创建一个逻辑类,用于处理业务逻辑和状态管理。定义处理用户输入和交互的方法:
// logic.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'util/toast_util.dart';
class LoginLogic extends GetxController {
final LoginState state = LoginState();
final TextEditingController controller = TextEditingController();
void wxLogin() {
ToastUtil.show(msg: '微信登录');
}
void next(BuildContext context) {
if (!state.isAgree.value) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: RichText(
text: TextSpan(
text: '请阅读并同意',
style: const TextStyle(color: Colors.black, fontSize: 16),
children: [
TextSpan(
text: '《BOSS直聘用户协议》',
style: const TextStyle(color: RC.themeColor),
recognizer: TapGestureRecognizer()
..onTap = () {
ToastUtil.show(msg: "跳转到BOSS直聘用户协议");
},
),
const TextSpan(
text: ' 和 ',
style: TextStyle(color: Colors.black, fontSize: 16),
),
TextSpan(
text: '《隐私政策》',
style: const TextStyle(color: RC.themeColor),
recognizer: TapGestureRecognizer()
..onTap = () {
ToastUtil.show(msg: "跳转到隐私政策");
},
),
const TextSpan(
text: ',允许BOSS直聘统一管理本人账号信息',
style: TextStyle(color: Colors.black, fontSize: 16),
),
],
),
),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text(
'拒绝',
style: TextStyle(
fontSize: 16,
color: RC.themeColor,
),
),
),
TextButton(
onPressed: () {
state.isAgree.value = true;
Navigator.of(context).pop();
},
child: const Text(
'同意',
style: TextStyle(
fontSize: 16,
color: RC.themeColor,
),
),
),
],
);
},
);
return;
}
ToastUtil.show(msg: '下一步');
}
}
class LoginState {
RxString phoneNum = "".obs;
RxBool isAgree = false.obs;
}
4. 主程序入口
在您的主文件中,将登录页面添加到应用程序的路由中:
// main.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'login_page.dart';
import 'logic.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
home: LoginPage(),
initialBinding: BindingsBuilder(() {
Get.lazyPut<LoginLogic>(() => LoginLogic());
}),
);
}
}
结论
通过以上步骤,我们已经完成了Boss登录页面的UI效果。
网友评论