Flutter 仿寫微信發現、我的頁面
這是我參與11月更文挑戰的第5天,活動詳情檢視:2021最後一次更文挑戰
發現頁面實現
這裡我們仿照微信的發現頁面用 Flutter
類實現這頁面的簡單佈局及每個 cell
的點選效果及點選每條 cell
之後跳轉到一個新的頁面。這裡我們分幾步分別來實現這些功能。
自定義 cell
針對 cell
的佈局我們可以分為兩部分,左邊跟右邊,左邊是主圖片加標題,右邊是子標題、 子圖片加箭頭。主圖片名稱、主標題、子標題、子圖片名稱這些都可以由於 cell
初始化的時候由外部傳進來。這裡主圖片、標題跟箭頭是固定的每個 cell
都有的,子標題、 子圖片是可選的。針對 cell
佈局的程式碼如下。
String title;
String imageName;
String subTitle;
String subImageName;
DiscoverCell(this.title, this.imageName, this.subTitle, this.subImageName);
Container(
color: _currentColor,
height: 55,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// left
Container(
padding: EdgeInsets.all(10),
child: Row(
children: [
// 圖示
Image(image: AssetImage(widget.imageName), width: 20,),
// 間隙
SizedBox(width: 15,),
// Title
Text(widget.title),
],
),
),
// right
Container(
padding: EdgeInsets.all(10),
child: Row(
children: [
// subTitle
widget.subTitle != null ? Text(widget.subTitle) : Text(''),
// subImage
widget.subImageName.length > 0 ? Image.asset(widget.subImageName, width: 15,) : Container(),
// 箭頭
Image(image: AssetImage('images/icon_right.png'), width: 15,)
],
),
),
],
),
)
列表佈局
class _DiscoverPageState extends State<DiscoverPage> {
Color _themColor = Color.fromRGBO(230, 230, 230, 1.0);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: _themColor,
// 安卓裡面用到,切 app 的時候顯示
centerTitle: true,
title: Text('發現'),
elevation: 0.0,
),
body: Container(
height: 800,
color: _themColor,
child: ListView(
children: [
DiscoverCell('朋友圈', 'images/朋友圈.png', '', ''),
SizedBox(height: 10,),
DiscoverCell('掃一掃', 'images/掃一掃2.png', '', ''),
//分割線
Row(
children: [
// 左邊線條
Container(width: 50, height: 0.5, color: Colors.white,),
// 右邊線條
Container(height: 0.5, color: Colors.grey,)
],
),
DiscoverCell('搖一搖', 'images/搖一搖.png', '', ''),
SizedBox(height: 10,),
DiscoverCell('看一看', 'images/看一看icon.png', '', ''),
//分割線
Row(
children: [
// 左邊線條
Container(width: 50, height: 0.5, color: Colors.white,),
// 右邊線條
Container(height: 0.5, color: Colors.grey,)
],
),
DiscoverCell('搜一搜', 'images/搜一搜.png', '', ''),
SizedBox(height: 10,),
DiscoverCell('附近的人', 'images/附近的人icon.png', '', ''),
SizedBox(height: 10,),
DiscoverCell('購物', 'images/購物.png', '雙十一限時特價', 'images/badge.png'),
Row(
children: [
// 左邊線條
Container(width: 50, height: 0.5, color: Colors.white,),
// 右邊線條
Container(height: 0.5, color: Colors.grey,)
],
),
DiscoverCell('遊戲', 'images/遊戲.png', '', ''),
SizedBox(height: 10,),
DiscoverCell('小程式', 'images/小程式.png', '', ''),
],
),
)
);
}
}
針對列表的佈局我們用的是 ListView
,在 children
裡面按順序新增每條 cell
資料,這裡每組之間的間隔我們用 SizedBox
,cell
上的下劃線我們用 Row
來實現,分為左邊線條跟右邊線條。
cell 點選跳轉
return GestureDetector(
// cell 手勢點選
onTap: (){
Navigator.of(context).push(
MaterialPageRoute(builder:
(BuildContext context) => DiscoverChildPage(widget.title)
)
);
這裡我們定義一個新的頁面 DiscoverChildPage
標題由 cell
點選的時候傳入。在 cell
中我們新增點選方法,然後 push
到一個新的頁面。
cell 新增點選狀態
GestureDetector(
// cell 手勢點選
onTap: (){
Navigator.of(context).push(
MaterialPageRoute(builder:
(BuildContext context) => DiscoverChildPage(widget.title)
)
);
setState(() {
_currentColor = Colors.white;
});
},
// cell 手勢點選下去
onTapDown: (TapDownDetails details){
setState(() {
_currentColor = Colors.grey;
});
},
// cell 手勢點選取消
onTapCancel: (){
setState(() {
_currentColor = Colors.white;
});
},
child: Container(
color: _currentColor,
),
);
為 cell
加上點選狀態的話就需要繼承於有狀態的 Widget
,然後在不同的點選狀態下設定不同的顏色,然後呼叫 setState
方法。因為呼叫 setState
方法的時候會重新構建 widget
,所以針對複雜的控制元件的時候我們只讓需要改變狀態的子控制元件繼承於 StatefulWidget
,把需要改變的部分抽取出來。我們這裡因為 cell
整體的子控制元件也不多,所以我們就直接讓 cell
繼承於 StatefulWidget
。也是為了偷下懶🐶。
我的頁面實現
我的頁面首先我們可以分為兩大塊,列表跟相機,這裡我們採用 Stack
部件來佈局。其中列表部分又可以分為兩大塊頭部跟底部 cell
部分。按照這種佈局思路我們的程式碼如下。
```
class _MinePageState extends State
@override Widget build(BuildContext context) { return Scaffold( body: Container( color: Color.fromRGBO(230, 230, 230, 1.0), child: Stack( children: [ // 列表 Container( child: MediaQuery.removePadding( removeTop: true, context: context, child: ListView( children: [ // 頭部 headerWidget(),
// 列表
SizedBox(height: 10,),
DiscoverCell('支付', 'images/微信 支付.png', '', ''),
SizedBox(height: 10,),
DiscoverCell('收藏', 'images/微信收藏.png', '', ''),
//分割線
Row(
children: [
// 左邊線條
Container(width: 50, height: 0.5, color: Colors.white,),
// 右邊線條
Container(height: 0.5, color: Colors.grey,)
],
),
DiscoverCell('朋友圈', 'images/微信相簿.png', '', ''),
//分割線
Row(
children: [
// 左邊線條
Container(width: 50, height: 0.5, color: Colors.white,),
// 右邊線條
Container(height: 0.5, color: Colors.grey,)
],
),
DiscoverCell('卡包', 'images/微信卡包.png', '', ''),
//分割線
Row(
children: [
// 左邊線條
Container(width: 50, height: 0.5, color: Colors.white,),
// 右邊線條
Container(height: 0.5, color: Colors.grey,)
],
),
DiscoverCell('表情', 'images/微信表情.png', '', ''),
SizedBox(height: 10,),
DiscoverCell('設定', 'images/微信設定.png', '', ''),
],
)
),
),
// 相機
Container(
margin: EdgeInsets.only(right: 10, top: 25),
height: 25,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Image(image: AssetImage('images/相機.png')),
],
),
),
],
),
),
);
} } ```
總結:其實實現這些佈局的方式有很多,如果需要評定哪種佈局方式更好的話,我們遵循頁面複雜度最低的佈局方式總歸是沒有錯的。
- Swift - LeetCode - 學生出勤記錄 I
- Swift - LeetCode - 字串中的第一個唯一字元
- Swift - LeetCode - 猜數字大小
- Swift - LeetCode - 翻轉二叉樹
- Swift - LeetCode - 二叉樹的後序遍歷
- Swift - LeetCode - 二叉樹的前序遍歷
- Swift String、Moya 原始碼解析及高階函式
- Flutter 中 key 的原理及作用
- Flutter 生命週期及渲染原理
- Flutter 仿寫微信搜尋頁
- Flutter 網路請求類封裝及搜尋框實現
- Flutter 佈局聊天列表頁及網路資料處理
- Flutter 通訊錄索引條完善及聊天資料配置
- Flutter 仿寫微信通訊錄頁面
- Flutter 仿寫微信發現、我的頁面
- Flutter 專案搭建及工程配置
- 常用 Widget 部件介紹及 Flutter 佈局方式
- Flutter 之 Widget 部件體驗
- Dart 基礎語法
- 記憶體管理-弱引用分析