Flutter 仿微信支付界面
左側(cè)是微信支付的界面,右側(cè)是開發(fā)完成后的效果,圖標是從 iconfont 上下載的。首先介紹一下本篇涉及到的組件。
帶裝飾效果的 Container
實際過程中我們經(jīng)常會遇到一個容器需要額外的樣式,例如圓角,背景色等。在 Flutter 中,對于各種容器都有一個 decoration 的屬性,可以用于裝飾容器。典型的用法有設(shè)置背景色、圓角、邊框和陰影等,其中背景色可以使用漸變色。decoration 是一個 Decoration 對象,最常用的是 BoxDecoration,BoxDecoration 的屬性如下所示:
const BoxDecoration({ this.color, this.image, this.border, this.borderRadius, this.boxShadow, this.gradient, this.backgroundBlendMode, this.shape = BoxShape.rectangle, })
其中color為使用顏色填充容器,image 為 使用圖片作為背景,border 為邊框,borderRadius 為邊框圓角,boxShadow 為容器陰影,gradient 使用漸變色作為背景,backgroundBlendMode 是指與容器的混合模型,默認是覆蓋,shape 是背景形狀,默認是矩形。其中背景部分我們一般只會選擇一種。這里以上面的綠色圓弧背景為例,還加上了一點點漸變(漸變色支持多個,可以根據(jù)需要調(diào)節(jié)),示例代碼如下:
return Container( //...... decoration: BoxDecoration( borderRadius: BorderRadius.circular(4.0), gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFF56AF6D), Color(0xFF56AA6D), ]), ), //... );
這里設(shè)置了邊角為圓弧,半徑為4,使用漸變色填充,漸變方向為從頂部中央到底部中央,漸變色有兩個。
Row 行布局和 Column列布局
這個在之前的第五篇列表篇介紹過,其中 Row 代表行布局(即子元素按一行排布),Column 代表列布局(即子元素按一列排布)。具體可以參考Flutter 入門與實戰(zhàn)(五):來一個圖文并茂的列表。
ListView列表組件
列表視圖,和之前的一篇一樣,只是本篇的用法不同,用于實現(xiàn)整個頁面可以按列表的方式進行滾動,直接將各個部分組件放入到列表的 children屬性中,而不是使用數(shù)組構(gòu)建列表元素,有點類似滾動視圖的用法。
GridView網(wǎng)格組件
GridView 用于將一個容器按行列劃分,可以指定主軸的元素個數(shù)(根據(jù)滾動方向定),之后自動按總元素的個數(shù)分別填充到網(wǎng)格,例如按縱向滾動時,則可以指定行方向一行有多少個網(wǎng)格,每個網(wǎng)格一個元素。超出一行數(shù)量后會自動換另一行。最簡單的用法是使用 GridView.count 方法構(gòu)建 GridView,用法如下:
GridView.count( crossAxisSpacing: gridSpace, mainAxisSpacing: gridSpace, crossAxisCount: crossAxisCount, //設(shè)置以下兩個參數(shù),禁止GridView的滾動,防止與 ListView 沖突 shrinkWrap: true, physics: NeverScrollableScrollPhysics(), children: buttons.map((item) { return _getMenus(item['icon'], item['name'], color: textColor); }).toList(), );
這里 crossAxisSpacing 是與滾動方向垂直的元素的間距,如按縱向(默認值)滾動,則是橫向行元素之間的間距。mainAxisSpacing 是與滾動方向相同的元素的間距。children 即網(wǎng)格中的元素。這里需要注意的是,由于 本例中GridView是嵌套在 ListView 里面的,兩個組件都是縱向滾動,這樣會引起沖突導(dǎo)致布局無法滿足約束。因此,在這里設(shè)置了 shrinkWrap 為 true 和 physics 為NeverScrollableScrollPhysics,以禁止 GridView 的滾動,從而滿足約束。
代碼實現(xiàn)
首先來分析布局,所有菜單按鈕其實都是一樣的布局,可以使用統(tǒng)一的列布局完成菜單按鈕,提高復(fù)用性。菜單按鈕從上到下一次為圖標、間距(圖標與文字之間)和菜單名稱。實現(xiàn)代碼如下:
Column _getMenus(String icon, String name, {Color color = Colors.black}) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ SizedBox( child: Image.asset(icon), width: 50, height: 50, ), SizedBox( height: 5, ), Text(name, style: TextStyle(fontSize: 14.0, color: color, height: 2)), ], );
通過傳輸一個圖標名稱,菜單名稱和可選的字體顏色(頂部區(qū)域和其他的文字顏色不同)來實現(xiàn)單個菜單。
其次來看頂部區(qū)域,頂部區(qū)域只有兩個按鈕,使用帶裝飾的容器實現(xiàn)背景的裝飾和圓角。再采用行布局將兩個菜單按鈕在橫向均勻排布。同時,使用 Center 布局將兩個菜單保持中部居中。這里指定了容器的高度,這是因為從美觀上看太矮了不太協(xié)調(diào),實際開發(fā)要根據(jù) UI 設(shè)計稿定。
Widget _headerGridButtons() { double height = 144; List<Map<String, String>> buttons = GridMockData.headerGrids(); return Container( height: height, margin: EdgeInsets.fromLTRB(MARGIN, MARGIN, MARGIN, MARGIN / 2), decoration: BoxDecoration( borderRadius: BorderRadius.circular(4.0), gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFF56AF6D), Color(0xFF56AA6D), ]), ), child: Center( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: buttons .map((item) => _getMenus(item['icon'], item['name'], color: Colors.white)) .toList()), ), ); }
其他菜單布局都是一樣,只是區(qū)域標題,菜單數(shù)量、菜單內(nèi)容不同,因此可以統(tǒng)一封裝一個通用的方法來構(gòu)建任意形式的菜單,以及設(shè)置區(qū)域標題的字體樣式、圓角背景等屬性。菜單均使用 GridView 實現(xiàn)網(wǎng)格式布局,同時由于菜單布局相同,可以封裝一個通用的方法來指定網(wǎng)格一行按鈕的數(shù)量,按鈕字體顏色等屬性,實現(xiàn)代碼的復(fù)用。
Widget _dynamicGridButtons(List<Map<String, String>> buttons, String title, {int crossAxisCount = 4}) { return Container( margin: EdgeInsets.fromLTRB(MARGIN, MARGIN, MARGIN, MARGIN / 2), padding: EdgeInsets.all(MARGIN), decoration: BoxDecoration( borderRadius: BorderRadius.circular(4.0), color: Colors.white, ), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle(color: Colors.grey[700]), ), SizedBox(height: 20), _gridButtons(buttons, crossAxisCount, textColor: Colors.black), ], ), ); } GridView _gridButtons(List<Map<String, String>> buttons, int crossAxisCount, {Color textColor = Colors.white}) { double gridSpace = 5.0; return GridView.count( crossAxisSpacing: gridSpace, mainAxisSpacing: gridSpace, crossAxisCount: crossAxisCount, //設(shè)置以下兩個參數(shù),禁止GridView的滾動,防止與 ListView 沖突 shrinkWrap: true, physics: NeverScrollableScrollPhysics(), children: buttons.map((item) { return _getMenus(item['icon'], item['name'], color: textColor); }).toList(), ); } }
ListView 構(gòu)建完整頁面:實際的整個頁面很簡單,只需要將各個區(qū)域放入到 ListView 的 children 屬性即可,從這里也可以看出,將子組件盡可能細化,不但能夠提高代碼復(fù)用性,還可以降低嵌套層級,提高代碼的可讀性和可維護性。
@override Widget build(BuildContext context) { return Scaffold( body: ListView( children: [ _headerGridButtons(), _dynamicGridButtons(GridMockData.financeGrids(), '金融理財'), _dynamicGridButtons(GridMockData.serviceGrids(), '生活服務(wù)'), _dynamicGridButtons(GridMockData.thirdpartyGrids(), '購物消費'), ], ), ); }
Mock 數(shù)據(jù)準備
按鈕數(shù)據(jù)均使用 Mock 數(shù)據(jù),這里只是返回一個 List<Map<String, String>>數(shù)組對象,對象里是每個菜單的圖標文件名稱和菜單名稱,下面是金融服務(wù)區(qū)域的菜單 Mock方法。
static List<Map<String, String>> financeGrids() { return [ {'name': '信用卡還款', 'icon': 'images/grid-buttons/grid-1-1.png'}, {'name': '借錢', 'icon': 'images/grid-buttons/grid-1-2.png'}, {'name': '理財', 'icon': 'images/grid-buttons/grid-1-3.png'}, {'name': '保險', 'icon': 'images/grid-buttons/grid-1-4.png'}, ]; }
其他待改進的地方:從代碼中可以看出,訪問按鈕的時候是使用 Map 對象的鍵來訪問的,需要使用['name']或['icon']來訪問,這種方式非常不利于編碼,而且很容易拼寫錯誤。因此,實際使用中應(yīng)當將 Json 對象(即 Map)轉(zhuǎn)換為實體類,這樣就可以通過訪問實體類的屬性來設(shè)置菜單的參數(shù),實際維護起來更為方便。
結(jié)語:
Flutter 提供的基礎(chǔ) UI 組件庫能夠滿足絕大部分復(fù)雜頁面布局,通過各種布局組件的組合即可完成。因此,熟悉基礎(chǔ)的布局組件的特性十分重要。同時,需要注意組件的拆分和抽離完成子組件的封裝,提高復(fù)用性的同時也避免了嵌套層級過深的問題。
以上就是Flutter 仿微信支付界面的實現(xiàn)的詳細內(nèi)容,更多關(guān)于Flutter 微信支付界面的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
android 跳轉(zhuǎn)進市場的實現(xiàn)代碼
本篇文章是對android中跳轉(zhuǎn)進市場的實現(xiàn)代碼進行了詳細的分析介紹,需要的朋友參考下2013-06-06說說在Android如何使用服務(wù)(Service)的方法
這篇文章主要介紹了說說在Android如何使用服務(wù)(Service)的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06Android播放assets文件里視頻文件相關(guān)問題分析
這篇文章主要介紹了Android播放assets文件里視頻文件相關(guān)問題分析,結(jié)合Android播放assets文件出現(xiàn)錯誤的實際問題給出了原因分析與解決方法參考,需要的朋友可以參考下2016-08-08Android中使用SeekBar拖動條實現(xiàn)改變圖片透明度(代碼實現(xiàn))
這篇文章主要介紹了Android中使用SeekBar拖動條實現(xiàn)改變圖片透明度,需要的朋友可以參考下2020-01-01Android Studio升級4.1.1后各種錯誤和解決方案
這篇文章主要介紹了Android Studio升級4.1.1后各種錯誤和解決方案,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12Android開發(fā)實戰(zhàn)之漂亮的ViewPager引導(dǎo)頁
這篇文章主要介紹了Android開發(fā)實戰(zhàn)中漂亮ViewPager引導(dǎo)頁的制作過程,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-08-08android之視頻播放系統(tǒng)VideoView和自定義VideoView控件的應(yīng)用
這篇文章主要介紹了android之視頻播放系統(tǒng)VideoView和自定義VideoView控件的應(yīng)用,需要的朋友可以參考下2017-03-03Flutter實現(xiàn)單選,復(fù)選和開關(guān)組件的示例代碼
在App開發(fā)過程中,選擇交互是非常常見的,今天主要介紹下關(guān)于選擇的三個組件的使用:開關(guān)、單選和復(fù)選,感興趣的小伙伴可以了解一下2022-04-04Ubantu16.04進行Android 8.0源碼編譯的流程
這篇文章主要介紹了Ubantu16.04進行Android 8.0源碼編譯的相關(guān)資料,需要的朋友可以參考下2018-02-02