上面文章我們初步進行了項目搭建招狸,下面就來開發(fā)微信項目的發(fā)現(xiàn)頁面
自定義cell
通過微信發(fā)現(xiàn)頁面的UI圖,我們知道Cell
需要對外提供四個屬性title
嗤栓、subTitle
烈菌、imageName
矮嫉、subImageName
用于頁面展示
- 新建自定義
Cell
文件滑臊,名稱為discover_cell.dart
import 'package:flutter/material.dart';
class DiscoverCell extends StatelessWidget {
final String title;
final String subTitle;
final String imageName;
final String subImageName;
DiscoverCell({
// @required表示必須要有title imageName值
@required this.title,
this.subTitle,
@required this.imageName,
this.subImageName
// 添加assert斷言痰娱,進行提示
}) : assert(title != null, 'title 不能為空'), assert(imageName != null, 'imageName 不能為空');
@override
Widget build(BuildContext context) {
return Container(
// Cell添加背景色
color: Colors.white,
height: 55,
child: Row(
// 主軸是spaceBetween
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
//left
Container(
padding: EdgeInsets.all(10),
child: Row(
children: [
Image(
image: AssetImage(imageName),
width: 20,
),
SizedBox(
width: 15,
),
Text(title),
],
),
),
//right
Container(
padding: EdgeInsets.all(10),
child: Row(
children: [
subTitle != null ? Text(subTitle) : Text(''),
subImageName != null
? Image(
image: AssetImage(subImageName),
width: 12,
)
: Container(),
Image( //右側(cè)箭頭
image: AssetImage('images/icon_right.png'),
width: 15,
)
],
),
),
],
),
);
}
}
發(fā)現(xiàn)頁面完善
discover_page.dart
文件添加ListView
import 'package:flutter/material.dart';
import 'discover_cell.dart';
class DiscoverPage extends StatefulWidget {
@override
_DiscoverPageState createState() => _DiscoverPageState();
}
class _DiscoverPageState extends State<DiscoverPage> {
Color _themeColor = Color.fromRGBO(220, 220, 220, 1.0);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: _themeColor,
//以下三個是專門為了安卓使用的屬性弃榨,title用于安卓退出后臺頂部顯示app名稱
centerTitle: true,
title: Text('發(fā)現(xiàn)'),
elevation: 0.0, //設置NaviBar底部邊欄為隱藏
),
body: Container(
color: _themeColor,
height: 800,
child: ListView(
children: <Widget>[
DiscoverCell(
imageName: 'images/朋友圈.png',
title: '朋友圈',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/掃一掃2.png',
title: '掃一掃',
),
// cell分隔線
Row(
children: <Widget>[
Container(width: 50, height: 0.5, color: Colors.white),
Container(height: 0.5, color: Colors.grey)
],
),
DiscoverCell(
imageName: 'images/搖一搖.png',
title: '搖一搖',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/看一看icon.png',
title: '看一看',
),
Row(
children: <Widget>[
Container(width: 50, height: 0.5, color: Colors.white),
Container(height: 0.5, color: Colors.grey)
],
),
DiscoverCell(
imageName: 'images/搜一搜 2.png',
title: '搜一搜',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/附近的人icon.png',
title: '附近的人',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/購物.png',
title: '購物',
subTitle: '618限時特價',
subImageName: 'images/badge.png',
),
Row(
children: <Widget>[
Container(width: 50, height: 0.5, color: Colors.white),
Container(height: 0.5, color: Colors.grey)
],
),
DiscoverCell(
imageName: 'images/游戲.png',
title: '游戲',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/小程序.png',
title: '小程序',
),
],
),
));
}
}
cell點擊切換頁面
上面我們實現(xiàn)了發(fā)現(xiàn)頁面的列表,但是Cell還無法點擊
梨睁,下面實現(xiàn)Cell點擊以及跳轉(zhuǎn)邏輯
-
cell
添加手勢GestureDetector
鲸睛,添加完手勢點擊cell
就會有回調(diào)事件onTap
// discover_cell.dart文件中添加手勢
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print('haha _$title');
},
child: Container(
// Cell添加背景色
color: Colors.white,
height: 54,
......
- 新建二級頁面
discover_child_page.dart
,用于cell
跳轉(zhuǎn)
import 'package:flutter/material.dart';
class DiscoverChildPage extends StatelessWidget {
final String title;
DiscoverChildPage({this.title});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('$title'),
),
body: Center(
child: Text('$title'),
),
);
}
}
- 在
GestureDetector
回調(diào)方法onTap
中添加跳轉(zhuǎn)邏輯
// 導入頭文件
import 'discover_child_page.dart';
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
// 添加跳轉(zhuǎn)二級頁面方法
Navigator.of(context).push(
// BuildContext上下文
MaterialPageRoute(builder: (BuildContext context) =>
DiscoverChildPage(title: '$title')
)
);
},
child: Container(
// Cell添加背景色
color: Colors.white,
height: 54,
......
注意??:如果不小心點到Pub get
導致flutter卡住坡贺,一般是網(wǎng)絡的原因
官辈,也有可能是不小心改動了pubspec.yaml
文件,復制一份重新配置遍坟。
有狀態(tài)的cell
Widget
與界面的關系
-
Widget
是界面的描述
拳亿,并不是界面。 - 如果
cell
內(nèi)容非常復雜愿伴,出于性能考慮肺魁,需要把cell
部分改成有狀態(tài)的
。 - 如果
cell
整體是有狀態(tài)的隔节,界面的描述會被整體改變
鹅经。 - 如果
cell
整體是有狀態(tài)的胡桨,渲染的時候并不是整體渲染,而是整個cell
的Widget
會重新創(chuàng)建瞬雹。為了提高性能昧谊,可以把cell
的部分Widget
抽取出來做成可變的
,而整個cell
是不可變的酗捌。 - 如果整個
cell
是不可變的呢诬,在創(chuàng)建對象的時候,cell不會重新創(chuàng)建胖缤,而是cell內(nèi)部的Widget
會重新創(chuàng)建尚镰,也就是Container
會重新創(chuàng)建。
GestureDetector
手勢的點擊狀態(tài)
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print('haha _$title');
Navigator.of(context).push(
MaterialPageRoute(builder: (BuildContext context) =>
DiscoverChildPage(title: '$title')
)
);
},
// 點擊
onTapDown: (TapDownDetails details) {
print('點下來了哪廓!');
},
// 取消點擊
onTapCancel: () {
print('離開了狗唉!');
},
......
// 控制臺成功打印
flutter: 點下來了!
flutter: 離開了涡真!
flutter: 點下來了分俯!
flutter: haha _DiscoverCell.title
- 修改
DiscoverCell
為有狀態(tài)的
import 'package:flutter/material.dart';
import 'discover_child_page.dart';
class DiscoverCell extends StatefulWidget {
final String title;
final String subTitle;
final String imageName;
final String subImageName;
DiscoverCell({
// @required表示必須要有title imageName值
required this.title,
this.subTitle,
required this.imageName,
this.subImageName
// 添加assert斷言,進行提示
}) : assert(title != null, 'title 不能為空'), assert(imageName != null, 'imageName 不能為空');
// 有狀態(tài)的Widget需要實現(xiàn)createState方法
@override
State<StatefulWidget> createState() => _DiscoverCellState();
}
// 問題一 _DiscoverCellState訪問不到DiscoverCell中的 title等屬性哆料?
// 解決方法 使用 widget.title, _DiscoverCellState中使用widget,這里的widget就是DiscoverCell
class _DiscoverCellState extends State<DiscoverCell> {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print('haha _$widget.title');
Navigator.of(context).push(
MaterialPageRoute(builder: (BuildContext context) =>
DiscoverChildPage(title: widget.title)
)
);
},
onTapDown: (TapDownDetails details) {
print('點下來了缸剪!');
},
onTapCancel: () {
print('離開了!');
},
child: Container(
// Cell添加背景色
color: Colors.white,
height: 54,
child: Row(
// 主軸是spaceBetween
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
//left
Container(
padding: EdgeInsets.all(10),
child: Row(
children: [
Image(
image: AssetImage(widget.imageName),
width: 20,
),
SizedBox(
width: 15,
),
Text(widget.title),
],
),
),
//right
Container(
padding: EdgeInsets.all(10),
child: Row(
children: [
widget.subTitle != null ? Text(widget.subTitle) : Text(''),
widget.subImageName != null
? Image(
image: AssetImage(widget.subImageName),
width: 12,
)
: Container(),
Image( //右側(cè)箭頭
image: AssetImage('images/icon_right.png'),
width: 15,
)
],
),
),
],
),
),
);
}
}
問題: _DiscoverCellState訪問不到DiscoverCell中的 title等屬性东亦?
解決方法:_DiscoverCellState
中使用widget.title
來訪問DiscoverCell
中的title
屬性杏节,這里的widget
就是DiscoverCell
-
color
抽取出來,通過手勢點擊修改cell
背景色
class _DiscoverCellState extends State<DiscoverCell> {
Color _currentColor = Colors.white;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print('haha _$widget.title');
Navigator.of(context).push(
MaterialPageRoute(builder: (BuildContext context) =>
DiscoverChildPage(title: widget.title)
)
);
setState(() {
_currentColor = Colors.white;
});
},
onTapDown: (TapDownDetails details) {
print('點下來了典阵!');
setState(() {
_currentColor = Colors.grey;
});
},
onTapCancel: () {
print('離開了奋渔!');
setState(() {
_currentColor = Colors.white;
});
},
child: Container(
// Cell添加背景色
color: _currentColor,
height: 54,
......
我的頁面布局
新建discover
文件夾右擊 -> new -> package
壮啊,把發(fā)現(xiàn)相關頁面放入
-
mine_page.dart
文件中編寫內(nèi)容 -
MediaQuery.removePadding
內(nèi)屬性removeTop: true,
可以去掉劉海屏頂部的默認偏移
import 'package:flutter/material.dart';
import 'discover/discover_cell.dart';
class MinePage extends StatefulWidget {
@override
_MinePageState createState() => _MinePageState();
}
class _MinePageState extends State<MinePage> {
Widget headerWidget() {
return Container(
height: 200,
color: Colors.red,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Color.fromRGBO(220, 220, 220, 1),
child: Stack(
children: [
//列表嫉鲸,用Container包一層會更靈活一點,方便抽出來
Container(
//Flutter官方封裝的一些屬性K蕖充坑!
child: MediaQuery.removePadding(
// 去掉劉海屏頂部的偏移部分
removeTop: true,
context: context,
child: ListView(
children: [
//頭部
headerWidget(),
//list
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/微信 支付.png',
title: '支付',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/微信收藏.png',
title: '收藏',
),
Row(
children: <Widget>[
Container(
width: 50, height: 0.5, color: Colors.white),
Container(height: 0.5, color: Colors.grey)
],
), //分割線
DiscoverCell(
imageName: 'images/微信相冊.png',
title: '相冊',
),
Row(
children: <Widget>[
Container(
width: 50, height: 0.5, color: Colors.white),
Container(height: 0.5, color: Colors.grey)
],
), //分割線
DiscoverCell(
imageName: 'images/微信卡包.png',
title: '卡包',
),
Row(
children: <Widget>[
Container(
width: 50, height: 0.5, color: Colors.white),
Container(height: 0.5, color: Colors.grey)
],
), //分割線
DiscoverCell(
imageName: 'images/微信表情.png',
title: '表情',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/微信設置.png',
title: '設置',
),
],
)
),
),
//相機 --也可以嘗試用Positioned實現(xiàn)
Container(
// 可以專門抽出一個文件配置這些 顏色 margin 等變量,color: Colors.red, Top Margin 40
margin: EdgeInsets.only(top: 40, right: 15),
height: 25,
child: Row(
mainAxisAlignment: MainAxisAlignment.end, //主軸方向在右側(cè)
children: [
Image(image: AssetImage('images/相機.png')),
],
),
),
],//
),
),
);
}
}
我的頁面頭部
我的頁面頭部染突,自定義小部件headerWidget
開發(fā)
- 獲取屏幕寬度
MediaQuery.of(context).size.width
Widget headerWidget() {
return Container(
height: 200,
color: Colors.white,
child: Container(
child: Container(
margin: EdgeInsets.only(top: 100, bottom: 20, left: 20, right: 10),
// color: Colors.red,
child: Row(
children: [
//頭像
Container(
width: 70,
height: 70,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(12),
image: DecorationImage(
image: AssetImage('images/Hank.png'),
fit: BoxFit.cover)),
),
//右邊的部分,包一個Expanded,懶得算了辈灼。
Expanded(
child: Container(
// color: Colors.red,
// margin:
// EdgeInsets.only(top: 10, bottom: 10, left: 10, right: 5),
// width: MediaQuery.of(context).size.width - 100,
padding: EdgeInsets.only(left: 10, top: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: 35,
child: Text(
'HK',
style: TextStyle(fontSize: 25, color: Colors.black),
),
), //昵稱
Container(
height: 35,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'微信號:12334',
style: TextStyle(fontSize: 17, color: Colors.grey),
),
Image(
image: AssetImage('images/icon_right.png'),
width: 15,
)
],
),
), //微信號+箭頭
],
),
)),
],
),
),
),
);
}