这是我参与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<MinePage> {
Widget headerWidget() {
return Container(
height: 200,
color: Colors.white,
child: Container(
margin: EdgeInsets.only(top: 90, bottom: 20, left: 16, right: 10),
child: Row(
children: [
// 头像
Container(
width: 70,
height: 70,
// 设置圆角属性
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: DecorationImage(
image: AssetImage('images/ChenXi.JPG')
)
),
),
// 右边部分
Expanded(child: Container(
padding: EdgeInsets.only(left: 10, top: 8, right: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 昵称
Container(
height: 35,
child: Text('Chenxi', style: TextStyle(fontSize: 25, color: Colors.black87),)
),
// 微信号加箭头
Container(
height: 35,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('微信号:CX123', style: TextStyle(fontSize: 17, color: Colors.grey),),
Image(image: AssetImage('images/icon_right.png'), width: 15,)
],
),
),
],
),
)),
],
),
),
);
}
@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')),
],
),
),
],
),
),
);
}
}
总结:其实完成这些布局的方法有许多,如果需求鉴定哪种布局方法更好的话,咱们遵从页面复杂度最低的布局方法总归是没有错的。