iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
1
Mobile Development

Flutter App 開發實戰系列 第 3

來做個登入畫面吧 [DAY 3]

大致了解過常用的 widget 後我們可以開始來看看怎麼實作一個比較完整的登入畫面,因為這次的登入只使用到第三方登入所以就不會需要輸入帳號密碼, textview 的部分就不會練習到了,不過後面應該還是會有機會看到的,第三方登入目前選用 FB 登入希望能在在下一篇開始實作。


目前的登入畫面包含

  • 背景
  • 標題
  • 登入按鈕

這幾個部分我們可以來大致看看該怎麼做,大家也可以自己實作看看,說不定這樣會有更多收穫

登入畫面

這是我們今天要刻的畫面
https://ithelp.ithome.com.tw/upload/images/20200904/20130127zDtv1RS5Qx.png

開始實作

框架

需要全螢幕沒有 app bar 所以我就不選用 scaffold 當基本的框架
我們可以看到畫面主要分成兩層,需要有上下層次所以選用 Stack
第一層使用 Image 當作背景圖片,
第二層使用 Column 用來排列標題、按紐

Stack(
      fit: StackFit.expand,
      children: <Widget>[
        Image.asset(),
        Column(
          children: <Widget>[],
        )
      ],
    );

背景

使用圖片需要先匯入資源檔

  1. project底下 > 右鍵 > New > Directory > create assetes!
  2. assets > 右鍵 > New > Directory > create images
  3. 將圖片放到 images https://ithelp.ithome.com.tw/upload/images/20200904/20130127hRDhSQSSCY.png
  4. 打開 pubspec.yaml
  5. 新增圖片路徑
flutter:

  assets:
    - assets/images/whiteCar.jpg

https://ithelp.ithome.com.tw/upload/images/20200904/20130127LLVs8n7cEB.png

Image.asset(
    "assets/images/whiteCar.jpg" ,
    fit: BoxFit.fill,
)

補充:
BoxFit 種類
BoxFit.fill 透過寬高比失真來填滿
BoxFit.contain 盡量大但要完全包含
BoxFit.cover 盡量小但要完全覆蓋
BoxFit.fitWidth 符合寬度
BoxFit.fitHeight 符合高度
BoxFit.none 不改變圖片
參考 :https://api.flutter.dev/flutter/painting/BoxFit-class.html

標題

標題包含大標題跟副標題 都是透過 Text 來顯示

            Text("熊熊洗車",
                style: TextStyle(
                    color:Colors.black ,
                    fontSize: 70 ,
                    fontWeight:FontWeight.bold,
                    decoration: TextDecoration.none
                )
            ),
            Text("bear friends 汽機車修理及清潔",
                style: TextStyle(
                    color:Colors.black ,
                    fontSize: 20 ,
                    fontWeight:FontWeight.bold,
                    decoration: TextDecoration.none
                )
            ),

補充:
不知道為何只要沒有加 decoration: TextDecoration.none 就會產生下底線
有人知道為何會這樣嗎?可以在底下留言告訴我感謝各位。

登入按鈕

就是利用上回我們我做的 loginBtn 來使用,還是有做一些修改

class LoginBtn extends StatelessWidget {
  const LoginBtn({
    Key key,
    this.color = const Color(0xFF2DBD3A),
    this.child ,
    this.onPressed
  }) : super(key: key);

  final Color color ;
  final Widget child ;
  final Function() onPressed ;
  @override
  Widget build(BuildContext context) {
  //引入sizeBox 來調整 btn 大小
    return SizedBox(
      height: 50,
      width: MediaQuery.of(context).size.width*0.9,
      child:RaisedButton(
        color: color,
        child: child ,
        onPressed: onPressed,
      ),
    );
  }
}
//MediaQuery.of(context).size.width 可以取得目前螢幕的寬度

讓我們來組合

 @override
  Widget build(BuildContext context) {
    final loginBtn  =  LoginBtn(
      onPressed: _login ,
      //FB Color 
      color:Color.fromARGB(255, 66, 103, 178),
      child: Text(
        "Facebook Login" ,
        style: TextStyle(color: Colors.white ,
            fontWeight: FontWeight.bold ,
            fontSize:18
        ),
      ),

    ) ;
    return Stack(
      fit: StackFit.expand,
      children: <Widget>[
        Image.asset("assets/images/whiteCar.jpg" , fit: BoxFit.fill,),
        Column(

          children: <Widget>[
            Padding(padding: EdgeInsets.only(top: 50.0)),
            Text("熊熊洗車",
                style: TextStyle(
                    color:Colors.black ,
                    fontSize: 70 ,
                    fontWeight:FontWeight.bold,
                    decoration: TextDecoration.none
                )
            ),
            Text("bear friends 汽機車修理及清潔",
                style: TextStyle(
                    color:Colors.black ,
                    fontSize: 20 ,
                    fontWeight:FontWeight.bold,
                    decoration: TextDecoration.none
                )
            ),
            Spacer(),
            loginBtn,
            Padding(padding: EdgeInsets.only(top: 50.0)),
        ],)
      ],
    );
  }
  //用 Spacer 填滿剩下的空間

這樣應該就能完成一個簡單的登入畫面了,不過需求總是會變動的,如果今天需要增加 Google 登入該怎麼做呢?
大家可以自己嘗試看看喔!

https://ithelp.ithome.com.tw/upload/images/20200904/20130127Ie9FdEdzVo.png


上一篇
來做個登入畫面吧 [DAY 2]
下一篇
FB 登入功能 [DAY 4]
系列文
Flutter App 開發實戰30

1 則留言

0
gatelynch
iT邦新手 5 級 ‧ 2020-09-04 07:32:46

先新增一個 loginGoogleBtn 並放在 loginBtn之下?

final loginGoogleBtn  =  LoginBtn(
      onPressed: _login ,
      //FB Color 
      color:Colors.white,
      child: Text(
        "Google Login" ,
        style: TextStyle(color: Colors.grey ,
            fontWeight: FontWeight.bold ,
            fontSize:18
        ),
      ),

    ) ;

不過我還想請教在 LoginBtn的Constructor函式中

const LoginBtn({
    Key key,
    this.color = const Color(0xFF2DBD3A),
    this.child ,
    this.onPressed
  }) : super(key: key);

: super(key: key); 這段是什麼意思?

Leo iT邦新手 5 級 ‧ 2020-09-04 12:47:19 檢舉

super(key : key) 的功能是會呼叫父類別的建構子

LoginBtn 繼承了 Staless 所以
會把 key 往上傳遞到 Stataless > Widget 。
一般來說如果父類的建構子沒有傳遞參數,子類在生成的時候就會自動去引用,但是因為這邊需要把 key 傳送到 widget,有傳遞參數就必須去呼叫 super(key : key)。

而 key 的功能可以用來識別是哪個 widget ,如果 element tree 上關聯的 widget 跟新的 widget key 相同的話就會被更新,我們也能透過 key 來在外部改變 widget 的狀態,不過目前應該是用不到。
更詳細的內容可以參考官方的 doc 。
關於 key :https://api.flutter.dev/flutter/foundation/Key-class.html

gatelynch iT邦新手 5 級 ‧ 2020-09-04 22:03:30 檢舉

瞭解~非常謝謝您~
所以換句話說,只要我們不在建構函式中,傳入key的話
就不需要 呼叫 父類的構造函式 super(key:key)

我要留言

立即登入留言