Flutter - 项目实战 - 仿微信(二)发现页面
接上篇:7、Flutter - 项目实战 - 仿微信(一)BottomNavigationBar 4个主页面显示
详细代码参见Demo
其他相关联文章
7、Flutter - 项目实战 - 仿微信(一)BottomNavigationBar 4个主页面显示
10、Flutter - 项目实战 - 仿微信(四)数据准备
12、Flutter - 项目实战 - 仿微信(六)聊天页面
效果:
创建文件夹discover
把前面创建的 discover_page 放进去。
如上图分析,这种在iOS中做的话应该用一个UITableView来实现,在Flutter 里面有一个列表的显示是ListView,里面可以放我们想要的widget
那就先创建一个cell,将ListView 中的widget 抽出来实现一下
1、discover_cell.dart
1.1、代码
标题:title
子标题:subTitle 例如:618这样的活动名
标题前面的图片:imageName
子标题后的图片:subImageName 例如:618后面的红点
最后面的箭头因为都有,就写死了这里,不再用变量
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({
this.title,
this.subTitle,
this.imageName,
this.subImageName,
}) : assert(title != null, 'title 不能为空'),
assert(imageName != null, 'imageName 不能为空');
@override
State<StatefulWidget> createState() {
return _DiscoverCellState();
}
}
class _DiscoverCellState extends State<DiscoverCell> {
Color _currentColor = Colors.white;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
//单击
print('hello');
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => DiscoverChildPage(
title: widget.title,
))); //push跳转
setState(() {
_currentColor = Colors.white;
});
},
onTapDown: (TapDownDetails details) {
//手势点击的时候变灰
setState(() {
_currentColor = Colors.grey;
});
},
onTapCancel: () {
//手势离开
print('离开了!');
setState(() {
_currentColor = Colors.white;
});
},
child: Container(
color: _currentColor,
height: 54,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, //左右两边对齐
children: <Widget>[
//left
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Image(
image: AssetImage(widget.imageName),
width: 20,
),
SizedBox(width: 15),
Text(widget.title),
],
),
),
//right
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
widget.subTitle != null ? Text(widget.subTitle) : Text(''),
widget.subImageName != null
? Container(
child: Image(
image: AssetImage(widget.subImageName),
width: 15,
),
margin: EdgeInsets.only(left: 10, right: 10),
)
: Container(),
Image(
image: AssetImage('images/icon_right.png'),
width: 15,
),
],
),
)
],
),
),
);
}
}
1.2、GestureDetector 手势的识别
本质是 StatelessWidget,里面包括了多种手势 class GestureDetector extends StatelessWidget {}
手势的冲突及其他更多可参考: https://www.jianshu.com/p/dc4853c33562
1.2.1、onTap(){}, 点击事件
点击的时候,通过push跳转到对应的页面,这里不做具体的页面了。用一个个统一的页面,动态修改title来实现
页面discover_child_page.dart 代码见2、discover_child_page.dart
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => DiscoverChildPage(
title: widget.title,
))); //push跳转
setState(() {
_currentColor = Colors.white;
});
push到discover_child_page 页面,调用 DiscoverChildPage设置title 为 当前点击的widget.title
然后将cell的背景色修改为白色(_currentColor = Colors.white;)(点击的时候修改为灰色,便于区分点击的cell)
1.2.2、onTapDown: (TapDownDetails details) {} 点击点击开始
点击开始的时候修改cell背景色为灰色
1.2.3、onTapCancel: () {} 手势点击离开
手势离开的的时候修改cell背景为白色
2、discover_child_page.dart
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'),
),
);
}
}
这个页面就一个导航栏、title和页面中央显示一下title的内容,所以没什么好说的
3、discover_page.dart
import 'package:flutter/material.dart';
import 'package:wechat/pages/discover/discover_cell.dart';
class DiscoverPage extends StatefulWidget {
@override
_ChatPageState createState() => _ChatPageState();
}
class _ChatPageState extends State<DiscoverPage> {
Color _themeColor = Color.fromRGBO(220, 220, 220, 1.0);
double _left_distance = 50;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: _themeColor,
centerTitle: true, //安卓需要
title: Text('发现'),
elevation: 0.0, //底部边栏
),
body: Container(
color: _themeColor,
height: 800,
child: ListView(
children: <Widget>[
DiscoverCell(
imageName: 'images/朋友圈.png',
title: '朋友圈',
),
SizedBox(
//加一个横向的分割条,设置一个高度
height: 10,
),
DiscoverCell(
imageName: 'images/扫一扫.png',
title: '扫一扫',
),
Row(
children: <Widget>[
Container(
width: _left_distance,
height: 0.5,
color: Colors.white,
),
Container(
height: 0.5,
)
],
),
DiscoverCell(
imageName: 'images/摇一摇.png',
title: '摇一摇',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/看一看icon.png',
title: '看一看',
),
Row(
children: <Widget>[
Container(
width: _left_distance,
height: 0.5,
color: Colors.white,
),
Container(
height: 0.5,
)
],
),
DiscoverCell(
imageName: 'images/搜一搜.png',
title: '搜一搜',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/附近的人icon.png',
title: '附近的人',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/购物.png',
title: '购物',
subImageName: 'images/badge.png',
subTitle: '618限时特价',
),
Row(
children: <Widget>[
Container(
width: _left_distance,
height: 0.5,
color: Colors.white,
),
Container(
height: 0.5,
)
],
),
DiscoverCell(
imageName: 'images/游戏.png',
title: '游戏',
),
SizedBox(
height: 10,
),
DiscoverCell(
imageName: 'images/小程序.png',
title: '小程序',
),
],
),
),
);
}
}
3.1、导航栏
导航栏这里centerTitle 这是安卓中需要配置的,让title居中。
elevation 设置其在图层最上层
3.2、body 页面
ListView 类似iOS的tableView,是列表视图
然后顺序的去添加DiscoverCell
在cell之间会有一条分割线,而且这个分割线是从文字开始的。这里用一个横向布局来实现
Row(
children: <Widget>[
Container(
width: _left_distance,
height: 0.5,
color: Colors.white,
),
Container(
height: 0.5,
)
],
),
前面用一个白色的、后面用灰色的,这样做出来的线就是从文字开始的分割线了
宽的分割线是自己而是用
SizedBox(
height: 10,
),
做完之后可以运行看一下。这个页面比较简单,具体代码应该全部贴了出来,如有其他不明白可以下载demo看一下,具体的一些控件或者布局可以自行上网搜一下,或者看Dart、Flutter的官方文档。
如有不正确还望指正,共同进步。