本系列可能会伴随大家很长时间,这里我会从0开始搭建一个「网易云音乐」的APP出来。
下面是该APP 功能的思维导图:
前期回顾:
1.Flutter实战 | 从 0 搭建「网易云音乐」APP(一、创建项目、添加插件、通用代码)
2.Flutter实战 | 从 0 搭建「网易云音乐」APP(二、Splash Page、登录页、发现页)
3.Flutter实战 | 从 0 搭建「网易云音乐」APP(三、每日推荐、推荐歌单)
本篇为第四篇,在这里我们会搭建排行榜页面、播放歌曲页面。
先来看图:
页面很简单,两个列表:
1.官方榜 -> ListView
2.更多榜单 -> GridView
注意:这里一定要使用这个接口,才会出现每个榜单中的1. 2. 3. 首歌。
话不多说,直接来看接口返回值:
返回值大致如此(删除了一部分用不到的数据)。
可以看到我标了两个红框框,这就是该接口 list
参数中不一样的地方:一个有歌,一个没有歌。
这代表了什么?这就是官方榜单和更多榜单的区别!
既然如此,区分的代码就如下了:
var officialTopListData =
data.list.where((l) => l.tracks.isNotEmpty).toList(); // 官方榜的数据
var moreTopListData =
data.list.where((l) => l.tracks.isEmpty).toList(); // 更多榜单的数据
只需要判断 tracks
的数据是否为空就好了。
然后就只需要根据各自的数据来创建列表就好了。
不过我这里「官方榜」也是列表的一部分。所以在点击 index 的时候,不要忘记 -1。
接下来就是跳转到「榜单详情页」。
因为开始在查看接口文档的过程中,找到了这样一段:
当时就想着在「榜单接口」中找到该id,但是我发现根本没有!
然而就当我绝望的时候在 GitHub 的 issue 中找到这么一段对话:
啊!!瞬间幸福感爆棚!页面我都不用写了,直接用原来的「歌单」页面就好了!
so easy!
「播放歌曲页面」可以说是整个APP的灵魂所在。
逻辑什么的之后再说,这节就单单来说UI。
如图所示:
播放
暂停
从上到下,七个部分:
1.标题(主标题、副标题)
2.唱针
3.碟片
4.对该歌曲的操作(喜欢、下载等)
5.进度条
6.对播放的操作(暂停、下一首等)
7.最后还有一个背景
首先,这里的标题是两行的。
AppBar 的title 需要的是一个 Widget,那我们就可以随意操作:
title: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
model.curSong.name,
style: commonWhiteTextStyle,
),
Text(
model.curSong.artists,
style: smallWhite70TextStyle,
),
],
)
装在唱机唱头上的针,一般由钢或人造宝石制成。它跟随声盘纹道的调制,把所得机械运动传送给唱头的换能元件,使之转换为相应的声频信号。
这里的唱针是一个图片,他的作用就是移开,放上,也就是对应着 播放、暂停。
这里有个问题是,唱针是个图片,我们要对该图片进行旋转操作,
而旋转的中心点左上角图中1的位置:
那我们就要对整个图片做一个了解,首先看看这个中心在原图的哪里:
用自带的看图工具大致看一下,在 45 * 45 的位置,然后查看一下原图的尺寸:
有了这两个参数我们就好定义中心点:
RotationTransition(
turns: _stylusAnimation,
alignment: Alignment(
-1 +
(ScreenUtil().setWidth(45 * 2) /
(ScreenUtil().setWidth(293))),
-1 +
(ScreenUtil().setWidth(45 * 2) /
(ScreenUtil().setWidth(504)))),
child: Image.asset(
'images/bgm.png',
width: ScreenUtil().setWidth(146.5),
height: ScreenUtil().setWidth(252),
),
),
首先我们设置该图片的宽高比和原图一致。
然后定义 Alignment,注意:
Alignment 左上角的值为:Alignment(-1.0, -1.0)
,
中心点的的值为:Alignment(0.0, 0.0)
,
右下角的值为:Alignment(1.0, 1.0)
;
从上面我们可以看得出来,Alignment 是从中心开始的坐标系,左和上为负数、右和下为正数。
那我们控制唱针的中心是在左上角,所以肯定是负数,所以我们用 -1+。
而既然是从中心开始的,那么计算的时候要用刚才看到的坐标 * 2 / 宽(高)。
这样得到的值才是准确的。
我们所看到的碟片有两种状态:
1.正在转2.停止
也是正好对应上 播放和暂停。
旋转的就不多说了,RotationTransition
了解一下。
监听一下状态,在完成的时候继续就可以了。
这个就比较简单了,一个Row 里面全是 Expanded
就可以了。
大致代码如下:
进度条也很简单,但是逻辑稍微复杂一点,我们后续再说。
进度条使用 Slider
就可以了。
关于 Slider
的样式,代码如下:
SliderTheme(
data: SliderThemeData(
trackHeight: ScreenUtil().setWidth(2),
thumbShape: RoundSliderThumbShape(
enabledThumbRadius: ScreenUtil().setWidth(10),
),
),
child: Slider(
value: double.parse(curTime),
onChanged: (data) {},
onChangeStart: (data){
model.pausePlay();
},
onChangeEnd: (data){
model.seekPlay(data.toInt());
},
activeColor: Colors.white,
inactiveColor: Colors.white30,
min: 0,
max: double.parse(totalTime),
),
),
在 Slider
上面套上 SliderTheme
就可以了。
这个也没什么好说的了,和上面对歌曲的操作一样。封装上一个组件,然后调用就好了。
背景还是使用的 BackdropFilter
,参数 sigma
设置成100。
这里模拟器和真机是有区别的,在模拟器上最多设置成20,再大就花了。
所以我建议跑播放歌曲的时候,最好用真机,不然会卡的要命。。
这一章节我们搭建了排行榜页面、播放歌曲页面。
其中「播放歌曲」页面是该APP的一个难点和重点。
我这里的逻辑也还没有写完,后续会慢慢捋出来发文的。
Copyright© 2013-2019