Flutter系列:2.實現一個簡單的登入介面

DandJ發表於2018-11-06

前言

上一篇文章Flutter系列:1.開發環境配置已經配置好了基本的開發環境,那麼這篇將直入主題,實現一個簡單的登入頁面,實現輸入使用者名稱密碼點選登入後驗證輸入有效性,模擬呼叫api登入,最終彈窗提示登入成功。

Flutter系列:2.實現一個簡單的登入介面

本示例程式碼在這裡Github.

tips: 在開始前,你應該快速瞭解下dart的基本語法

佈局

本示例算是一個比較常見的簡單app頁面,包括頂部的一個導航欄及其title, 然後一個白底的頁面,從上到下依次是一個圖片顯示控制元件,使用者名稱和密碼的文字輸入控制元件,以及一個提交的按鈕。

佈局方式

在開始Flutter佈局前,心中應該始終記住一個概念,那就是在Flutter佈局中顯示的都是Widget,包括看得見頁面、圖片、輸入框、按鈕...其他看不見的列布局控制元件('Column'), 容器佈局控制元件('Container')、('SizedBox'),使用者表單顯示的控制元件('Form') 甚至用作填充的控制元件('Padding'), 居中的控制元件('Center');

  • 從main函式開始
void main() {
  debugPaintSizeEnabled = false;
  runApp(new LoginAlertDemoApp());
}

class LoginAlertDemoApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        title: 'Login Alert',
        theme: new ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: Scaffold(
          appBar: AppBar(
            title: Text('Login Alert'),
          ),
          body: new LoginHomePage(),
        ));
  }
}
複製程式碼

main函式顧名思義,就是app執行的入口,debugPaintSizeEnabled是使用者除錯顯示的;然後是呼叫sdk的runApp方法,傳入一個Widget物件並將它顯示到螢幕上,所以此Widget便是APP顯示的基礎Widget,有點相當於iOS開發中的rootViewController來負責承載整個APP的顯示。

在此示例中傳入runApp方法的這個Widget是LoginAlertDemoApp,繼承自StatelessWidget;重寫了其build方法建立了一個MaterialApp的Widget。也就是說主要負責顯示的就是MaterialApp的物件,它是用於實現谷歌設計的一套material design設計風格的基礎顯示Widget,封裝了一系列的常用元件和導航控制,比如主題控制。從程式碼可以看到其home屬性是一個Scaffold物件,Scaffold也是material design的基礎元件之一,實現基本頁面佈局結構,比如頁面導航欄,同時也封裝了一系列的基礎控制元件,比如'抽屜頁',toast提示,底部sheet提示。基於material design風格的app基本上都是構建在這2個基礎控制元件之上的。

接下來就是我們自己實現的頁面佈局了,LoginHomePage繼承自StatefulWidget,注意到Widget有StatefulWidget和StatelessWidget之分,簡單的理解呢就是StatefulWidget是具有可變狀態的Widget, 它需要一個State來儲存其生命週期中的一些狀態資料,並在資料改變時通過setState通知到Widget及時更新。而StatelessWidget則是無狀態的,不需要維護其狀態,只是簡單的顯示。

所以我們需要_LoginHomePageState來維護LoginHomePage生命週期中的一些狀態變化資料,並通過build方法來實時構建LoginHomePage的顯示Widget。

基本控制元件

  • Form

頁面分析這是一個簡單的表單提交頁面,可以使用'Form'來進行佈局,同時也能很方便通過其State屬性的validate()方法來實現輸入驗證和提示。 validate()會呼叫TextFormField的validator來執行驗證。

  • Image

用於顯示圖片的,支援網路圖片和本地圖片,本地圖片需要新增到配置檔案中

# To add assets to your application, add an assets section, like this:
  # assets:
  #  - images/a_dot_burr.jpeg
  #  - images/a_dot_ham.jpeg
  assets:
    - images/lake.jpg
複製程式碼
  • TextFormField

Form中對應的文字輸入控制元件,validator用於驗證輸入的合法性,當驗證不通過時返回一個字串提示在輸入框的底部。

  • RaisedButton

按鈕,沒什麼好說的,onPressed指定點選回撥

  • Column

列布局,此demo中各控制元件從上到下依次佈局,Column再合適不過了。

  • 彈窗

呼叫AlertDialog顯示一個文字的Widget。

第三方元件

此demo中使用了一個第三方的載入提示元件flutter_spinkit

main.dart頂部程式碼

import 'package:flutter_spinkit/flutter_spinkit.dart';
複製程式碼

這是引入的一個第三方載入提示元件flutter_spinkit,使用第三方元件前需要先到pubspec.yaml檔案新增依賴配置:

flutter_spinkit: "^2.1.0"
複製程式碼

儲存後VSCode會自動執行'flutter packages get'下載元件。

使用程式碼:

final _loadingContainer = Container(
    constraints: BoxConstraints.expand(),
    color: Colors.black12,
    child: Center(
        child: Opacity(
            opacity: 0.9,
            child: SpinKitWave(
              color: Colors.red,
              size: 50.0,
            ),
        ),
    )
);
複製程式碼

非同步操作

點選按鈕後執行的是以下程式碼:

  void _toggleSubmit() {
    if (_formKey.currentState.validate()) {
      setState(() {
        _showLoading = true;
      });

      _loginRequest().then((onValue) {
        setState(() {
          _showLoading = false;
        });
        showDialog(
            context: context,
            builder: (context) {
              String alertText = 'login success!' +
                  ' \nuserName:' +
                  _userNameTextController.text +
                  '\npassWord:' +
                  _passwordTextController.text;
              return AlertDialog(
                content: Text(alertText),
              );
            });
      });
    }
  }
複製程式碼
  • 顯示隱藏載入框

首先通過預先指定的GlobalKey的currentState來拿到對應的FormState, 然後呼叫validate()方法執行驗證Form中的使用者名稱和密碼輸入內容,通過返回true,否則返回false; 然後通過setState()方法來更新_showLoading屬性為true或者false, 便會重新執行build方法,這樣就可以動態的顯示和隱藏載入框了。

  • 非同步操作
Future _loginRequest() async {
  return Future.delayed(Duration(seconds: 3), () {
    //do nothing
    print('login success');
  });
}
複製程式碼

_loginRequest函式返回的是一個Future, 用於dart支援非同步操作的關鍵字,顧名思義這個函式呼叫後會在未來執行而不是立刻執行,更多細節推薦閱讀flutter實戰5:非同步async、await和Future的使用技巧

在_loginRequest函式中,這裡只是簡單的執行延遲3秒操作來模擬api呼叫耗時,點選submit按鈕後呼叫此方法,此方法執行完成後呼叫then方法使用setState來隱藏載入框,同時彈出提示框顯示獲取到的使用者名稱和密碼。

_loginRequest().then((onValue) {
      setState(() {
        _showLoading = false;
      });
      showDialog(
          context: context,
          builder: (context) {
            String alertText = 'login success!' +
                ' \nuserName:' +
                _userNameTextController.text +
                '\npassWord:' +
                _passwordTextController.text;
            return AlertDialog(
              content: Text(alertText),
            );
          });
    });
    
複製程式碼

嗯,到此就差不多了,該準備下一個學習demo了,後續Demo持續更新...

參考

相關文章