1. 程式人生 > 實用技巧 >Flutter 登入頁面

Flutter 登入頁面

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

最後,如果大家覺得此專案程式碼對你點幫助,記得給我點贊哦!!!後續會不斷的更新專案程式碼,繼續的完成其他功能!!!
大家如果遇到什麼問題,評論區見!!!
相互學習,相互進步,記得點贊,謝謝!!!