Flutter实战 | 从 0 搭建「网易云音乐」APP(四、排行榜、播放页面)

2889次阅读  |  发布于4年以前

本系列可能会伴随大家很长时间,这里我会从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.最后还有一个背景

1. 标题

首先,这里的标题是两行的。

AppBar 的title 需要的是一个 Widget,那我们就可以随意操作:

title: Column(
  mainAxisSize: MainAxisSize.min,
  children: <Widget>[
    Text(
      model.curSong.name,
      style: commonWhiteTextStyle,
    ),
    Text(
      model.curSong.artists,
      style: smallWhite70TextStyle,
    ),
  ],
)

2. 唱针

装在唱机唱头上的针,一般由钢或人造宝石制成。它跟随声盘纹道的调制,把所得机械运动传送给唱头的换能元件,使之转换为相应的声频信号。

这里的唱针是一个图片,他的作用就是移开,放上,也就是对应着 播放、暂停。

这里有个问题是,唱针是个图片,我们要对该图片进行旋转操作,

而旋转的中心点左上角图中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 / 宽(高)。

这样得到的值才是准确的。

3. 碟片

我们所看到的碟片有两种状态:

1.正在转2.停止

也是正好对应上 播放和暂停。

旋转的就不多说了,RotationTransition 了解一下。

监听一下状态,在完成的时候继续就可以了。

4. 对该歌曲的操作(喜欢、下载等)

这个就比较简单了,一个Row 里面全是 Expanded 就可以了。

大致代码如下:

5. 进度条

进度条也很简单,但是逻辑稍微复杂一点,我们后续再说。

进度条使用 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 就可以了。

6. 对播放的操作(暂停、下一首等)

这个也没什么好说的了,和上面对歌曲的操作一样。封装上一个组件,然后调用就好了。

7. 背景

背景还是使用的 BackdropFilter,参数 sigma 设置成100。

这里模拟器和真机是有区别的,在模拟器上最多设置成20,再大就花了。

所以我建议跑播放歌曲的时候,最好用真机,不然会卡的要命。。

总结

这一章节我们搭建了排行榜页面、播放歌曲页面。

其中「播放歌曲」页面是该APP的一个难点和重点。

我这里的逻辑也还没有写完,后续会慢慢捋出来发文的。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8