欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Flutter 開發(fā)一個(gè)登錄頁面

 更新時(shí)間:2021年06月05日 11:08:05   作者:島上碼農(nóng)  
登錄頁面在 App 開發(fā)中非常常見,本篇借登錄頁面的開發(fā)介紹了文本框 TextField組件的使用,同時(shí)使用文本框的裝飾屬性實(shí)現(xiàn)了個(gè)性化文本框設(shè)置。

業(yè)務(wù)邏輯

為了演示登錄跳轉(zhuǎn),在分類瀏覽先做了一個(gè)簡單的按鈕,點(diǎn)擊跳轉(zhuǎn)到登錄頁面。實(shí)際的 App 中,通常會(huì)是觸發(fā)某些需要登錄才能查看的操作后再跳轉(zhuǎn)到登錄界面。

布局分析

界面如上圖所示,從界面上看,整體內(nèi)容區(qū)域是居中的,內(nèi)容的布局是一個(gè)簡單的列式布局,包括了頂部的一個(gè) Logo(通常是 App圖標(biāo)),再往下是兩個(gè)文本輸入框,最后是登錄按鈕。整體布局比較簡單,使用 Center 下嵌一個(gè)Column 進(jìn)行列布局即可。

圖片圓形裁剪

在 Flutter 中實(shí)行圖片圓形裁剪有兩個(gè)方式,一是使用外層的容器,通過將正方形的按圓形裁剪即可;二是使用內(nèi)置的 CircleAvatar。不過從名字上看 CircleAvatar 用于頭像的,因此這里使用容器的來實(shí)現(xiàn)圓形裁剪。封裝一個(gè)獲取圓形圖片的方法_getRoundImage,傳入圖片資源名稱和正方形邊長,代碼如下所示:

Widget _getRoundImage(String imageName, double size) {
    return Container(
      width: size,
      height: size,
      clipBehavior: Clip.antiAlias,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.all(Radius.circular(size / 2)),
      ),
      child: Image.asset(
        imageName,
        fit: BoxFit.fitWidth,
      ),
    );
  }

這里使用了 BoxDecoration 將邊框設(shè)置為圓形的邊框,半徑為邊長的一半,這樣就達(dá)到邊框是圓形的效果了。但是,需要額外設(shè)置一個(gè)屬性就是 clipBehavior,這是邊緣裁剪類型,默認(rèn)是不裁剪的。這里使用了 Clip.antiAlias(抗鋸齒)的方式進(jìn)行裁剪,這種方式的裁剪效果最好,但是更耗資源,其他的裁剪方式如下:

  • Clip.hardEdge:從名字就知道,這種方式很粗糙,但是裁剪的效率最快;
  • Clip.antiAliasSaveLayer:最為精細(xì)的裁剪,但是非常慢,不建議使用;
  • Clip.none:默認(rèn)值,如果內(nèi)容區(qū)沒有超出容器邊界的話,不會(huì)做任何裁剪。內(nèi)容超出邊界的話需要使用別的裁剪方式防止內(nèi)容溢出。

圓形扁平按鈕

這里需要提一下, Flutter 2.0以前的扁平按鈕是FlatButton,使用起來很簡單,但是很多場合不太滿足,因此2.0以后引入了 TextButton 替代。TextButton 多了一個(gè) style來裝飾按鈕樣式。具體可以看官方的文檔。這里我們的按鈕需要設(shè)置背景色為主題色,然后按鈕文字顏色為白色,同時(shí)需要切成圓角,因此還是使用 Container 的邊界圓弧來實(shí)現(xiàn)。需要注意的是,默認(rèn)按鈕的寬度是根據(jù)內(nèi)容來的,因此為了讓按鈕撐滿屏幕,我們設(shè)置了 Container 的寬度為 double.infinity。代碼如下所示:

Widget _getLoginButton() {
    return Container(
      height: 50,
      width: double.infinity,
      margin: EdgeInsets.all(10),
      decoration: BoxDecoration(
        color: Theme.of(context).primaryColor,
        borderRadius: BorderRadius.circular(4.0),
      ),
      child: TextButton(
        style: ButtonStyle(
          foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
          backgroundColor:
              MaterialStateProperty.all<Color>(Theme.of(context).primaryColor),
        ),
        child: Text(
          '登錄',
        ),
        onPressed: () {
          print(
              'Login: username=${_username.trim()}, password=${_password.trim()}');
        },
      ),
    );
  }

按鈕點(diǎn)擊回調(diào)事件為 onPressed,這里只是簡單地打印了表單的內(nèi)容。

TextField 文本框

TextField 是 Flutter 提供的文本輸入框,TextField 的屬性非常多,常用的屬性如下:

  • keyboardType:鍵盤類型,可以指定是數(shù)字、字母、電話號碼、郵箱、日期等多種方式,通過與表單內(nèi)容匹配的鍵盤類型可以提供輸入效率,進(jìn)而改善用戶體驗(yàn)。
  • controller:TextEditingController 對象,TextEditingController 主要用于控制文本框的初始值,清除內(nèi)容的操作。
  • obscureText:是否需要隱藏輸入內(nèi)容,如果為 true,則輸入內(nèi)容會(huì)使用圓點(diǎn)顯示,通常用與密碼。
  • decoration:文本框的裝飾,屬性也很多,可以指定前置圖標(biāo),邊框類型、后置組件等多種屬性,因此可以通過 decoration 獲得想要的文本框樣式。
  • focusNode:聚焦點(diǎn),可以通過這個(gè)來控制文本框是否獲取焦點(diǎn),從而實(shí)現(xiàn)類似上一個(gè)下一個(gè)的輸入控制。
  • onChanged:輸入值改變事件回調(diào),通常用這個(gè)方法實(shí)現(xiàn)雙向綁定。

在這個(gè)案例中,我們使用了一個(gè)前置圖標(biāo)用來表示輸入內(nèi)容的類型,比如使用手機(jī)圖標(biāo)代表輸入手機(jī)號,使用鎖代表代表密碼。同時(shí)使用了一個(gè) Offstage作為后置的組件,用于在輸入內(nèi)容后可以點(diǎn)擊清除內(nèi)容。Offstage 組件是通過一個(gè)屬性offstage來控制組件是否顯示,這樣我們可以在沒有內(nèi)容的時(shí)候隱藏它,有輸入內(nèi)容的時(shí)候再顯示。

為了提高代碼復(fù)用性,使用了一個(gè)方法獲取通用的文本框,這里主要是使用了 Container包裹以控制邊距和文本框下的分隔線:

Widget _getInputTextField(
    TextInputType keyboardType, {
    FocusNode focusNode,
    controller: TextEditingController,
    onChanged: Function,
    InputDecoration decoration,
    bool obscureText = false,
    height = 50.0,
  }) {
    return Container(
      height: height,
      margin: EdgeInsets.all(10.0),
      child: Column(
        children: [
          TextField(
            keyboardType: keyboardType,
            focusNode: focusNode,
            obscureText: obscureText,
            controller: controller,
            decoration: decoration,
            onChanged: onChanged,
          ),
          Divider(
            height: 1.0,
            color: Colors.grey[400],
          ),
        ],
      ),
    );
  }

完整代碼

class _LoginPageState extends State<LoginPage> {
  //TextEditingController可以使用 text 屬性指定初始值
  TextEditingController _usernameController = TextEditingController();
  TextEditingController _passwordController = TextEditingController();
  String _username = '', _password = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('登錄'),
        brightness: Brightness.dark,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _getRoundImage('images/logo.png', 100.0),
            SizedBox(
              height: 60,
            ),
            _getUsernameInput(),
            _getPasswordInput(),
            SizedBox(
              height: 10,
            ),
            _getLoginButton(),
          ],
        ),
      ),
    );
  }

  Widget _getUsernameInput() {
    return _getInputTextField(
      TextInputType.number,
      controller: _usernameController,
      decoration: InputDecoration(
        hintText: "輸入手機(jī)號",
        icon: Icon(
          Icons.mobile_friendly_rounded,
          size: 20.0,
        ),
        border: InputBorder.none,
        //使用 GestureDetector 實(shí)現(xiàn)手勢識別
        suffixIcon: GestureDetector(
          child: Offstage(
            child: Icon(Icons.clear),
            offstage: _username == '',
          ),
          //點(diǎn)擊清除文本框內(nèi)容
          onTap: () {
            this.setState(() {
              _username = '';
              _usernameController.clear();
            });
          },
        ),
      ),
      //使用 onChanged 完成雙向綁定
      onChanged: (value) {
        this.setState(() {
          _username = value;
        });
      },
    );
  }

  Widget _getPasswordInput() {
    return _getInputTextField(
      TextInputType.text,
      obscureText: true,
      controller: _passwordController,
      decoration: InputDecoration(
        hintText: "輸入密碼",
        icon: Icon(
          Icons.lock_open,
          size: 20.0,
        ),
        suffixIcon: GestureDetector(
          child: Offstage(
            child: Icon(Icons.clear),
            offstage: _password == '',
          ),
          onTap: () {
            this.setState(() {
              _password = '';
              _passwordController.clear();
            });
          },
        ),
        border: InputBorder.none,
      ),
      onChanged: (value) {
        this.setState(() {
          _password = value;
        });
      },
    );
  }

  //省略了上述列舉的代碼

}

頁面跳轉(zhuǎn)

在上層面的登錄按鈕上,我們增加了一個(gè)點(diǎn)擊事件,點(diǎn)擊后再跳到登錄頁,按鈕的響應(yīng)代碼如下所示。這是頁面跳轉(zhuǎn)的最簡單的方式,使用 Navigator 導(dǎo)航器的 push方法實(shí)現(xiàn)頁面跳轉(zhuǎn),后續(xù)會(huì)介紹如何通過路由實(shí)現(xiàn)頁面跳轉(zhuǎn),那種方式更為優(yōu)雅。

//...
onPressed: () {
  Navigator.of(context).push(
    MaterialPageRoute(builder: (context) => LoginPage()),
  );
},
//...

總結(jié)

從代碼上看,功能雖然實(shí)現(xiàn)了,但是構(gòu)建用戶名和密碼的代碼十分相似,有沒有辦法進(jìn)一步提高代碼復(fù)用率,構(gòu)建一個(gè)更為通用的表單組件呢?下篇我們將介紹如何來封裝。

以上就是Flutter 開發(fā)一個(gè)登錄頁面的詳細(xì)內(nèi)容,更多關(guān)于Flutter 開發(fā)登錄頁面的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Flutter項(xiàng)目在 iOS14 啟動(dòng)崩潰的解決方法

    Flutter項(xiàng)目在 iOS14 啟動(dòng)崩潰的解決方法

    這篇文章主要介紹了Flutter項(xiàng)目在 iOS14 啟動(dòng)崩潰的解決方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Android OKHTTP的單例和再封裝的實(shí)例

    Android OKHTTP的單例和再封裝的實(shí)例

    這篇文章主要介紹了Android OKHTTP的單例和再封裝的實(shí)例的相關(guān)資料,這里對OKHTTP的單例進(jìn)行了分析總結(jié),需要的朋友可以參考下
    2017-07-07
  • 詳談android界面之間數(shù)據(jù)的傳遞

    詳談android界面之間數(shù)據(jù)的傳遞

    下面小編就為大家?guī)硪黄斦刟ndroid界面之間數(shù)據(jù)的傳遞。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • 詳解如何在Android中實(shí)現(xiàn)懸浮Activity

    詳解如何在Android中實(shí)現(xiàn)懸浮Activity

    本篇文章主要介紹詳解如何在Android中實(shí)現(xiàn)懸浮Activity,通過修改Activity的實(shí)現(xiàn)來適配平板設(shè)備,已達(dá)到代碼的最大利用率。有興趣的可以了解一下。
    2017-01-01
  • 刷新Activity中的scrollview示例(局部ui刷新)

    刷新Activity中的scrollview示例(局部ui刷新)

    代碼很簡單,但是很實(shí)用,適合在一個(gè)Activity中要刷新局部的UI,比如在掃描一維碼的時(shí)候,要把每次掃描的結(jié)果都顯示在界面上
    2014-01-01
  • Android Activity 入門簡介

    Android Activity 入門簡介

    Activity 是一個(gè)應(yīng)用組件,用戶可與其提供的屏幕進(jìn)行交互,以執(zhí)行撥打電話、拍攝照片、發(fā)送電子郵件或查看地圖等操作,這篇文章主要介紹了Android Activity入門基礎(chǔ)知識,需要的朋友可以參考下
    2024-04-04
  • Android使用開源框架ANDROID-IMAGE-INDICATOR實(shí)現(xiàn)圖片輪播部署

    Android使用開源框架ANDROID-IMAGE-INDICATOR實(shí)現(xiàn)圖片輪播部署

    這篇文章主要為大家詳細(xì)介紹了Android使用開源框架ANDROID-IMAGE-INDICATOR實(shí)現(xiàn)圖片輪播部署,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android基于Flutter編寫文件下載管理器

    Android基于Flutter編寫文件下載管理器

    文件下載在很多類型的應(yīng)用中會(huì)涉及,例如音樂、文檔、包括圖片(只是圖片可以使用一些組件完成無感知的下載)。本篇介紹使用Flutter中的Dio下載方法完成文件的下載,需要的可以參考一下
    2022-03-03
  • Android實(shí)現(xiàn)斷點(diǎn)下載的方法

    Android實(shí)現(xiàn)斷點(diǎn)下載的方法

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)斷點(diǎn)下載的方法,感興趣的小伙伴們可以參考一下
    2016-03-03
  • Android應(yīng)用中使用ViewPager和ViewPager指示器來制作Tab標(biāo)簽

    Android應(yīng)用中使用ViewPager和ViewPager指示器來制作Tab標(biāo)簽

    這篇文章主要介紹了Android中使用ViewPager和ViewPager指示器來制作Tab標(biāo)簽的方法,ViewPager指示器ViewPageIndicator是一個(gè)開源庫,文中舉了一個(gè)仿網(wǎng)易新聞客戶端Tab標(biāo)簽的例子,需要的朋友可以參考下
    2016-03-03

最新評論