0%

Flutter笔记3-收藏交互

demo的功能如下:对词组列表加收藏功能,跳转到收藏夹页面,更改整个APP的主题。

  • 添加交互
  • 页面跳转
  • 更改主题

添加收藏图标

所有动态功能的实现还是在 State 中去做,找到 ListTile在后面增加收藏图标,类似iOS中UITableViewCell中的accessoryView,但添加方法不一样。

1
2
3
4
5
6
7
8
9
10
Widget _cellView(WordPair name) {
return ListTile(
title: Text(
name.asPascalCase
),
trailing: Icon( //在trailing上添加Icon,Icons的图标很多,favorite是个心形
Icons.favorite,
),
);
}

这样便为每一个Tile增加了收藏图标,收藏图标有两种状态——已收藏、未收藏。需要有个bool值去控制,要得到这个bool值就要对每个Tile的title判断,判断这个title是否被收藏。

这时需要有个数组专门存放已收藏的词组:

1
final Set<WordPair>_likeNameArray = Set<WordPair>();

这是存放收藏词组的数组,存放的类型是 `WordPair,用Set而不用List的原因是:Set中不允许有重复元素。更适合收藏操作。

_likeNameArray 中存放了收藏词组,在创建ListTile的方法中将每个WordPair值跟这个数组比对即可得到bool值。

1
final bool isLike = _likeNameArray.contains(name);

有了bool值便可修改收藏图标的状态:

1
2
3
4
trailing: Icon(
isLike ? Icons.favorite : Icons.favorite_border, //支持三目元算符,赋值不同收藏图标
color: isLike ? Colors.red : null, //为已收藏的心形设置红色,未收藏的不设置颜色
),

点击事件

有了收藏图标,需要增加收藏的点击交互。也是在创建ListTile的方法中为其添加点击事件onTap,在点击事件中操作收藏数据:

1
2
3
4
5
6
7
8
9
onTap: () {//点击事件
setState(() {//setState()方法
if (isLike) {
_likeNameArray.remove(name);//移除收藏
} else {
_likeNameArray.add(name);//收藏
}
});
},

flutter是响应式框架,setState()方法会为State对象触发build()方法,会让UI更新。点击的时候还有水波特效,是Material Design自带的。

至此,便能完成点击收藏和取消收藏的操作了。

导航栏按钮

在导航栏添加一个收藏夹按钮,点击收藏夹按钮跳转收藏夹页面。

appBar 中添加收藏夹按钮:

1
2
3
4
5
6
7
8
9
10
11
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('home'),
actions: <Widget>[//actions需要一个Widget组
new IconButton(icon: Icon(Icons.list), onPressed: _pushVc),
],
),
body: _listView(),
);
}

有些widget需要单个widget属性,actions需要一个widget组,可以添加多个IconButton,会把title挤到一边。类似iOS中的rightBarButtonItems

数组中是IconButton,设置了Icon,和点击事件_pushVc,这个方法中完成页面跳转操作。

页面跳转

页面跳转在iOS中是控制器跳转,常用push,页面称为控制器。在flutter中页面称为路由route,从主路由切换到新路由,就是页面跳转。

flutter中也是push和pop控制路由跳转,将路由push到导航器的栈中就是跳转新页面,将路由pop出导航器,就会返回上一个路由。

_pushVc方法中创建路由,并将其push到导航器的栈中。

1
2
3
void _pushVc() {
Navigator.push(context, route);//路由入栈的push方法,route处创建一个新路由
}

创建路由

MaterialPageRoute 中创建要显示的收藏夹列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Navigator.push(context, 
new MaterialPageRoute(
builder: (contex) {//1.在builder方法中构建路由,builder方法是匿名函数
final Iterable<ListTile> tiles = _likeNameArray.map(
(WordPair name) {
return new ListTile (//2. 创建ListTile:tiles
title: Text(
name.asPascalCase
),
);
},
);
final List<Widget> divided = ListTile //6. divided最后含有分割线的列表
.divideTiles(//3. ListTile的divideTiles()方法在每个tile之间添加1像素分割线,不用像之前判断奇偶添加Divider()
context: context,
tiles: tiles,//4. 这是上面根据收藏数组创建的ListTile
)
.toList();//5. 转换成列表显示
}
)
);

上述方法创建了收藏夹,还未结束,builder返回一个Scaffold,在这里将上面创建的列表添加到body,形成整个要push的路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void _pushVc() {
Navigator.push(context,
new MaterialPageRoute(
builder: (contex) {
final Iterable<ListTile> tiles = _likeNameArray.map(
(WordPair name) {
return new ListTile (
title: Text(
name.asPascalCase
),
);
},
);
final List<Widget> divided = ListTile
.divideTiles(
context: context,
tiles: tiles,
)
.toList();//创建收藏夹列表
return Scaffold(
appBar: AppBar(
title: Text('like'),//路由标题
),
body: ListView(children: divided), //路由内容
);
}
)
);
}

至此,完成路由跳转的工作。跳转之后在新路由页面自动添加返回按钮,点击会返回,不用额外添加pop。这点和iOS很像,而且也支持手势右滑返回页面。

更改主题

在flutter中,使用theme控制APP主题,可更改颜色修改主题:

1
2
3
theme: new ThemeData(
primaryColor: Colors.white,//白色主题
),

这里有个小坑,VSCode新建项目时,这个字段默认是primarySwatch,在设置白色时会报错。因为white和black是Color类型,不是MaterialColor。像yellow、blue等颜色属于MaterialColor

或者直接使用dark(),设置暗黑主题:

1
theme: new ThemeData.dark(),

demo的完整代码见工程中的 flutter_listview

打赏作者一杯咖啡