1. 程式人生 > >用flutter寫一個精美的登入頁面

用flutter寫一個精美的登入頁面

先看效果圖;
login

我們先看一下頁面 , 首先這個頁面,我們並沒有用到AppBar,當然也就沒有自帶返回功能.
然後下面有個Login的文字以及一條橫線.

螢幕中上方是填寫帳號以及密碼的2個輸入框,密碼輸入框有隱藏和顯示密碼的按鈕.

下方是登入按鈕 以及其他登入方式.

看一下主體佈局:

 return Scaffold(
        body: Form(
            key: _formKey,
            child: ListView(
              padding: EdgeInsets.symmetric(horizontal: 22.0),
              children: <Widget>[
                SizedBox(
                  height: kToolbarHeight,
                ),
                buildTitle(),
                buildTitleLine(),
                SizedBox(height: 70.0),
                buildEmailTextField(),
                SizedBox(height: 30.0),
                buildPasswordTextField(context),
                buildForgetPasswordText(context),
                SizedBox(height: 60.0),
                buildLoginButton(context),
                SizedBox(height: 30.0),
                buildOtherLoginText(),
                buildOtherMethod(context),
                buildRegisterText(context),
              ],
            )));

頁面在一個Scaffold中包裹著, 然後整體佈局是縱向的,於是我們用ListView來做外層控制元件,因為是有輸入框,所以我們又用了Form來包裹住整體.

標題部分

buildTitle(),
buildTitleLine(),

分別實現了Login的文字元件和下方的一個橫線元件.
Login:

Padding(
      padding: EdgeInsets.all(8.0),
      child: Text(
        'Login',
        style: TextStyle(fontSize: 42.0),
      ),
    );

橫線:

Padding(
      padding: EdgeInsets.only(left: 12.0, top: 4.0),
      child: Align(
        alignment: Alignment.bottomLeft,
        child: Container(
          color: Colors.black,
          width: 40.0,
          height: 2.0,
        ),
      ),
    );

可以看到,都是用Padding做外層元件,前者包裹了一個Text,後者包裹了一個Container.

輸入框

TextFormField buildPasswordTextField(BuildContext context) {
    return TextFormField(
      onSaved: (String value) => _password = value,
      obscureText: _isObscure,
      validator: (String value) {
        if (value.isEmpty) {
          return '請輸入密碼';
        }
      },
      decoration: InputDecoration(
          labelText: 'Password',
          suffixIcon: IconButton(
              icon: Icon(
                Icons.remove_red_eye,
                color: _eyeColor,
              ),
              onPressed: () {
                setState(() {
                  _isObscure = !_isObscure;
                  _eyeColor = _isObscure
                      ? Colors.grey
                      : Theme.of(context).iconTheme.color;
                });
              })),
    );
  }

  TextFormField buildEmailTextField() {
    return TextFormField(
      decoration: InputDecoration(
        labelText: 'Emall Address',
      ),
      validator: (String value) {
        var emailReg = RegExp(
            r"[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?");
        if (!emailReg.hasMatch(value)) {
          return '請輸入正確的郵箱地址';
        }
      },
      onSaved: (String value) => _email = value,
    );
  }

用TextFormField 來實現輸入框, 帳號我們規定是郵箱,所以用了正則表示式來驗證:

 var emailReg = RegExp(
            r"[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?");

如果不符合,在提交的時候會給出相應的提示.

密碼輸入那裡使用了判空的方法,多了一個顯示/隱藏密碼的按鈕:

 decoration: InputDecoration(
          labelText: 'Password',
          suffixIcon: IconButton(
              icon: Icon(
                Icons.remove_red_eye,
                color: _eyeColor,
              ),
              onPressed: () {
                setState(() {
                  _isObscure = !_isObscure;
                  _eyeColor = _isObscure
                      ? Colors.grey
                      : Theme.of(context).iconTheme.color;
                });
              })),

可以看到在decotation中設定,suffixIcon是在後面加一個圖示,這裡給它一個點選方法是改變是否顯示密碼的,並更改圖示的顏色.

登入

 Align buildLoginButton(BuildContext context) {
    return Align(
      child: SizedBox(
        height: 45.0,
        width: 270.0,
        child: RaisedButton(
          child: Text(
            'Login',
            style: Theme.of(context).primaryTextTheme.headline,
          ),
          color: Colors.black,
          onPressed: () {
            if (_formKey.currentState.validate()) {
              ///只有輸入的內容符合要求通過才會到達此處
              _formKey.currentState.save();
              //TODO 執行登入方法
              print('email:$_email , assword:$_password');
            }
          },
          shape: StadiumBorder(side: BorderSide()),
        ),
      ),
    );
  }

登入按鈕,是一個RaiseButton,點選的時候,我們判斷輸入框內容,符合條件會執行登入方法.

其他帳號登入

  ButtonBar buildOtherMethod(BuildContext context) {
    return ButtonBar(
      alignment: MainAxisAlignment.center,
      children: _loginMethod
          .map((item) => Builder(
                builder: (context) {
                  return IconButton(
                      icon: Icon(item['icon'],
                          color: Theme.of(context).iconTheme.color),
                      onPressed: () {
                        //TODO : 第三方登入方法
                        Scaffold.of(context).showSnackBar(new SnackBar(
                          content: new Text("${item['title']}登入"),
                          action: new SnackBarAction(
                            label: "取消",
                            onPressed: () {},
                          ),
                        ));
                      });
                },
              ))
          .toList(),
    );
  }

其他帳號登入,這裡我以facebook,twitter和google為例來實現的
ButtonBar是一個按鈕的組合,我們放了3個IconButton, 並在list中定義了支援的登入方式. 點選圖示實現對應的登入方法.

其他都是些text使用,跟login大致相同,不再介紹了,想了解請看原始碼.github