Flutter 一個漂亮的登錄頁面
項目地址: https://github.com/whiskyma/flutter_demo_login
flutter-demo-login 快速構建Flutter項目基礎模板搭建,並完成登錄頁制作.
所需組件如下:
組件 |
名稱 |
鏈接 |
底部導航切換 | bottomNavigationBar | https://book.flutterchina.club/chapter5/material_scaffold.html |
抽屜菜單 | Drawer | https://book.flutterchina.club/chapter5/material_scaffold.html |
Hero動畫 | Hero | https://book.flutterchina.club/chapter9/hero.html |
Loadding動畫 | flutter_spinkit | https://pub.dev/packages/flutter_spinkit |
Toast提示 | Toast | https://pub.dev/packages/toast |
.... | ... | .... |
登錄頁效果圖(效驗正則,按鈕禁用和登錄loadding狀態顯示):
設置和注冊頁:
各個路由組件:
main.dart代碼如下:
import 'package:flutter/material.dart';
import './router/index.dart';
import 'dart:io';
import 'package:flutter/services.dart';
void main() {
runApp(new MyApp());
if(Platform.isAndroid){ // 設置狀態欄背景及顏色
SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle(statusBarColor: Colors.transparent);
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '登錄Demo',
debugShowCheckedModeBanner: false,
routes: routes,
);
}
}
login.dart代碼如下:
import 'package:flutter/material.dart'; import '../components/common/toast.dart'; import '../components/common/loadding.dart'; class Login extends StatefulWidget{ @override _LoginState createState() => new _LoginState(); } class _LoginState extends State<Login>{ // 控制器 final _unameController = TextEditingController(); final _pwdController = TextEditingController(); final _formKey = GlobalKey<FormState>(); // 焦點 final focusNode1 = FocusNode(); final focusNode2 = FocusNode(); bool isEye = true; bool isBtnEnabled = false; bool showLoading = false; final _unameExp = RegExp(r'^(?![0-9]+$)(?![a-z]+$)[0-9a-z]{6,12}$'); //用戶名正則 final _pwdExp = RegExp(r'^(?![0-9]+$)(?![a-z]+$)[0-9a-z]{6,12}$'); //密碼正則 // 登錄按鈕是否可點擊 void checkLoginText(){ if(_unameExp.hasMatch(_unameController.text)&&_pwdExp.hasMatch(_pwdController.text)){ this.isBtnEnabled = true; }else{ this.isBtnEnabled = false; } } // 登錄提交 void loginSub(){ FocusScope.of(context).requestFocus(FocusNode()); //收起鍵盤 setState((){ this.showLoading = true; }); loginRequest().then((v) => { setState((){ this.showLoading = false; }), // toast提示 // 模擬登錄跳轉首頁 ToastCom.show('登錄成功', context), Navigator.pushNamed(context, '/') // showDialog( // context: context, // builder: (context){ // String alertText = "登錄成功!!!"+"\n用戶名:"+_unameController.text+"\n密碼:"+_pwdController.text; // return AlertDialog(content: Text(alertText)); // } // ) }); } @override void initState(){ super.initState(); } @override void dispose(){ super.dispose(); } // 異步操作 Future loginRequest() async { return Future.delayed(Duration(seconds: 3),(){ print('login success'); }); } @override Widget build(BuildContext context){ List<Widget> childrens = []; final _main = Center( child: ListView( padding: EdgeInsets.only(left: 30.0, right: 30.0,top: 70.0), children: [ Padding( padding: EdgeInsets.only(bottom: 40), child: Hero( tag: 'avatar', child: CircleAvatar( backgroundColor: Colors.transparent, radius: 50.0, child: Image.asset('assets/images/avatar.png'), ), ), ), Form( key: _formKey, autovalidate: true, child: Column( children: [ TextFormField( //用戶名 controller: _unameController, focusNode: focusNode1,//關聯focusNode1 keyboardType: TextInputType.text,//鍵盤類型 maxLength: 12, textInputAction: TextInputAction.next,//顯示'下一步' decoration: InputDecoration( hintText: '請輸入賬號', labelText: "賬號", contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), prefixIcon:Icon(Icons.perm_identity), border: OutlineInputBorder( borderRadius: BorderRadius.circular(40.0) //圓角大小 ), suffixIcon: _unameController.text.length>0?IconButton( icon: Icon( Icons.clear, size: 21, color: Color(0xff666666), ), onPressed: (){ setState(() { _unameController.text = ''; checkLoginText(); }); }, ):null ), validator: (v) { return !_unameExp.hasMatch(v)?'賬號由6到12位數字與小寫字母組成':null; }, onEditingComplete: ()=>FocusScope.of(context).requestFocus(focusNode2), onChanged: (v){ setState(() { checkLoginText(); }); }, ), SizedBox(height: 15.0), TextFormField( //密碼 controller: _pwdController, focusNode: focusNode2,//關聯focusNode1 obscureText: isEye, //密碼類型 內容用***顯示 maxLength: 12, textInputAction: TextInputAction.done, //顯示'完成' decoration: InputDecoration( hintText: '請輸入密碼', labelText: '密碼', contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), prefixIcon:Icon(Icons.lock), border: OutlineInputBorder( borderRadius: BorderRadius.circular(40.0) ), suffixIcon: IconButton( icon: Icon( Icons.remove_red_eye, size: 21, color: Color(0xff666666), ), onPressed: (){ setState(() { isEye = !isEye; }); }, ) ), validator:(v){ return !_pwdExp.hasMatch(v)?'密碼由6到12位數字與小寫字母組成':null; }, onChanged: (v){ setState(() { checkLoginText(); }); }, onEditingComplete: ()=>loginSub(), //'完成'回調 ) ], ), ), Padding( padding: EdgeInsets.symmetric(vertical: 5.0), child: RaisedButton( color: const Color(0xff2a8fbd), padding: EdgeInsets.symmetric(vertical: 10.0), // splashColor: const Color(0xffde19de),//水波紋顏色 disabledColor: const Color(0xff999999), shape:RoundedRectangleBorder(borderRadius: BorderRadius.circular(60.0)),//圓角 child: Text('登錄',style: TextStyle(fontSize: 18.0, color: Colors.white)), onPressed: !isBtnEnabled?null:loginSub, ), ), FlatButton( child: Text('忘記密碼?', style: TextStyle(color: Colors.black54,fontSize: 15.0)), onPressed: () { Navigator.pushNamed(context, 'forget'); }, ), ], ), ); childrens.add(_main); if(this.showLoading){ childrens.add(Loadding()); } return Scaffold( appBar: AppBar( iconTheme: IconThemeData(color: Colors.white), centerTitle: true, title: Text('登錄',style: TextStyle(color: Colors.white)), ), body: Stack(children: childrens), ); } }
項目地址: https://github.com/whiskyma/flutter_demo_login
最后,如果大家覺得此項目代碼對你點幫助,記得給我點贊哦!!!后續會不斷的更新項目代碼,繼續的完成其他功能!!!
大家如果遇到什么問題,評論區見!!!
相互學習,相互進步,記得點贊,謝謝!!!