import 'package:flutter/material.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:food_hub_app/widgets/common/index.dart'; import 'package:form_builder_validators/form_builder_validators.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPage(); } class _LoginPage extends State { final GlobalKey _formKey = GlobalKey(); late String _username, _password; bool _isObscure = true; Color _eyeColor = Colors.grey; final List _loginMethod = [ {"title": "phone", "icon": Icons.phone_android}, {"title": "email", "icon": Icons.email}, {"title": "wechat", "icon": Icons.wechat}, ]; void loginClick(BuildContext context) { // 表单校验通过才会继续执行 if ((_formKey.currentState as FormState).validate()) { (_formKey.currentState as FormState).save(); Navigator.pushNamed(context, '/home'); } else { showErrorToast("请先输入信息"); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[100], body: Form( key: _formKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: Column( children: [ // 可滚动的主要内容区域 Expanded( child: ListView( padding: const EdgeInsets.symmetric(horizontal: 20), children: [ const SizedBox(height: kToolbarHeight), buildTitle(), const SizedBox(height: 60), buildUsernameTextField(), const SizedBox(height: 20), buildPasswordTextField(context), // 紧凑排列:记住密码在上,忘记密码在下,间距缩小 const SizedBox(height: 8), // 缩小密码框与记住密码的间距 Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ buildRememberPasswordCheckbox(context), // 记住密码(左对齐) buildForgetPasswordText(context), ], ), const SizedBox(height: 20), // 调整与登录按钮的间距 buildLoginButton(context), ], ), ), // 固定在底部的其他登录选项区域 Padding( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 50), child: Column( children: [ buildOtherLoginText(), const SizedBox(height: 15), buildOtherMethod(context), const SizedBox(height: 20), buildRegisterText(context), ], ), ), ], ), ), ); } Widget buildTitle() { return const Text( '食光集', textAlign: TextAlign.center, style: TextStyle(fontSize: 42), ); } Widget buildUsernameTextField() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ formLabelText(labelText: "账号:"), const SizedBox(height: 5), FormBuilderTextField( name: 'username', decoration: formInputDecoration(hintText: "请输入账号", prefixIcon: Icons.person), validator: FormBuilderValidators.required(), onSaved: (v) => _username = v!, ), ], ); } Widget buildPasswordTextField(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ formLabelText(labelText: "密码:"), const SizedBox(height: 5), FormBuilderTextField( name: 'password', obscureText: _isObscure, // 是否显示文字 onSaved: (v) => _password = v!, validator: FormBuilderValidators.required(), decoration: InputDecoration( prefixIcon: Icon(Icons.lock), hintText: "请输入密码", hintStyle: TextStyle(color: Colors.grey), border: OutlineInputBorder(), filled: true, fillColor: Colors.white, suffixIcon: IconButton( icon: Icon(Icons.remove_red_eye, color: _eyeColor), onPressed: () { // 修改 state 内部变量, 且需要界面内容更新, 需要使用 setState() setState(() { _isObscure = !_isObscure; _eyeColor = (_isObscure ? Colors.grey : Theme.of(context).iconTheme.color)!; }); }, ), ), ) ], ); } Widget buildRememberPasswordCheckbox(BuildContext context) { return Row( children: [ Checkbox( value: false, onChanged: (bool? value) { print("记住密码: $value"); }, ), const Text('记住密码', style: TextStyle(color: Colors.grey, fontSize: 14)), ], ); } Widget buildForgetPasswordText(BuildContext context) { return Align( alignment: Alignment.centerRight, child: TextButton( onPressed: () { print("忘记密码"); }, child: const Text( "忘记密码?", style: TextStyle(fontSize: 14, color: Colors.grey), ), ), ); } Widget buildLoginButton(BuildContext context) { return Align( child: SizedBox( height: 45, width: double.infinity, child: ElevatedButton( style: ButtonStyle( backgroundColor: WidgetStateProperty.all(Colors.green), shape: WidgetStateProperty.all( RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), ), child: Text( '登录', style: TextStyle(fontSize: 24, color: Colors.white), ), onPressed: () => loginClick(context), ), ), ); } Widget buildOtherLoginText() { return SizedBox( width: double.infinity, child: Stack( alignment: Alignment.center, children: [ const Divider(color: Colors.grey, thickness: 0.5), Container( padding: const EdgeInsets.symmetric(horizontal: 16), color: Colors.white, // 与背景色一致,覆盖横线 child: const Text( '其他方式登录', style: TextStyle(color: Colors.grey, fontSize: 14), ), ), ], ), ); } Widget buildOtherMethod(context) { return OverflowBar( alignment: MainAxisAlignment.center, children: _loginMethod .map( (item) => Builder( builder: (context) { return IconButton( icon: Icon( item['icon'], color: Theme.of(context).iconTheme.color, ), onPressed: () { //TODO: 第三方登录方法 ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('${item['title']}登录'), action: SnackBarAction( label: '取消', onPressed: () {}, ), ), ); }, ); }, ), ) .toList(), ); } Widget buildRegisterText(context) { return Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text('没有账号?', style: TextStyle(fontSize: 18)), GestureDetector( child: const Text( '点击注册', style: TextStyle(fontSize: 18, color: Colors.green), ), onTap: () { print("点击注册"); }, ), ], ), ); } }