我的Android进阶之旅之Android自定义View来实现解析lrc歌词同步滚动、上下拖动、缩放歌词等功能
前言
最近有个项目有关于播放音乐时候,关于歌词有以下几个功能:
1、实现歌词同步滚动的功能,即歌曲播放到哪句歌词,就高亮地显示出正在播放的这个歌词;
2、实现上下拖动歌词时候,可以拖动播放器的进度。即可以不停地上下拖动歌词,当手指离开屏幕时候 即从当前拖动到的歌词位置播放。
3、实现歌词的字体大小可以进行缩放的功能。即双指在屏幕进行缩放操作时,歌词的字体大小也进行相应的缩放操作。
下面我将这几个功能做成一个demo来展示给大家。首先来看看这个demo的具体实现效果,如下面几幅图所示。
图1、同步滚动歌词
图2、上下拖动歌词1
图3、上下拖动歌词2
图4、缩放歌词
图5、歌词显示(较大字体)
图6、歌词显示(较小字体)
图7、歌词滚动时候,高亮地画出正滚动到的歌词内容以及歌词的开始时间,并该句歌词下面画出一条直线
一、LRC歌词文件简介
1、什么是LRC歌词文件
lrc是英文lyric(歌词)的缩写,被用做歌词文件的扩展名。以lrc为扩展名的歌词文件可以在各类数码播放器中同步显示。
2、LRC歌词文件的格式
先来看一份标准的LRC歌词文件,下面展示的是王力宏的《依然爱你》的lrc歌词的内容
[ti:依然爱你]
[ar:王力宏]
[al:火力全开 新歌+精选]
[by:欧阳鹏]
[00:01.17]一闪一闪亮晶晶 留下岁月的痕迹
[00:07.29]我的世界的重心 依然还是你
[00:13.37]一年一年又一年 飞逝尽在一转眼
[00:20.29]唯一永远不改变 是不停的改变
[00:27.14]我不像从前的自己 你也有点不像你
[00:33.36]但在我眼中你的笑 依然的美丽
[00:39.53]这次只能往前走 一个方向顺时钟
[00:46.12]不知道还要多久 所以要让你懂
[00:51.82]我依然爱你 就是唯一的退路
[00:57.36]我依然珍惜 时时刻刻的幸福
[01:04.65]你每个呼吸 每个动作 每个表情
[01:11.43]到最后一定会依然爱你
[01:18.08]依然爱你 依然爱你
[01:25.58]我不像从前的自己 你也有点不像你
[01:31.52]但在我眼中你的笑 依然的美丽
[01:37.61]这次只能往前走 一个方向顺时钟
[01:44.42]不知道还要多久 所以要让你懂
[01:50.18]我依然爱你 就是唯一的退路
[01:55.65]我依然珍惜 时时刻刻的幸福
[02:02.84]你每个呼吸 每个动作 每个表情
[02:09.77]到最后一定会依然爱你
[02:15.61]
[02:17.61]lrc制作:http://blog.csdn.net/ouyang_peng 欧阳鹏
[02:25.61]
[02:31.06]依然爱你 依然爱你
[02:36.63]
[02:42.32]我依然爱你 或许是命中注定
[02:47.70]多年之后 任何人都无法代替
[02:54.57]那些时光 是我这一辈子 最美好
[03:01.84]那些回忆 依然无法忘记
[03:07.88]我依然爱你 就是唯一的退路
[03:13.95]我依然珍惜 时时刻刻的幸福
[03:21.32]你每个呼吸 每个动作 每个表情
[03:28.20]到最后一定会依然爱你
[03:34.76]你每个呼吸 每个动作 每个表情
[03:42.04]到永远一定会依然爱你
[03:53.28]
[04:01.28]
LRC歌词文件的标签类型
lrc歌词文本中含有两类标签:一是标识标签 ,二是时间标签。
1、标识标签
标识标签,其格式为“[标识名:值]”,主要包含以下预定义的标签:
[ar:歌手名] [ti:歌曲名] [al:专辑名] [by:编辑者(指lrc歌词的制作人)] [offset:时间补偿值] (其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢的,但多数的MP3可能不会支持这种标签)。
2、时间标签
时间标签,形式为“[mm:ss]”或“[mm:ss.ff]”(分钟数:秒数.毫秒数),数字须为非负整数,
比如”[12:34.50]”是有效的,而”[0x0C:-34.50]”无效。
时间标签需位于某行歌词中的句首部分,一行歌词可以包含多个时间标签
(比如歌词中的迭句部分)。当歌曲播放到达某一时间点时,MP3就会寻找对应的时间标签并显示标签后面的歌词文本,这样就完成了“歌词同步”的功能。
例如下面的这首 草蜢的《失恋战线联盟》,就是一行歌词包含了多个时间标签。
[ti:失恋战线联盟]
[ar:草蜢]
[al:]
[00:00.00]草蜢-失恋战线联盟
[00:08.78]编辑:小婧
[01:43.33][00:16.27]她总是只留下电话号码
[01:46.97][00:19.81]从不肯让我送她回家
[01:50.61][00:23.43]听说你也曾经爱上过她
[01:54.15][00:27.07]曾经也同样无法自拔
[01:57.78][00:30.72]你说你学不会假装潇洒
[02:01.41][00:34.36]却叫我别太早放弃她
[02:05.05][00:37.99]把过去传说成一段神话
[02:08.70][00:41.59]然后笑你是一样的傻
[02:12.01][00:45.11]我们那么在乎她
[02:14.15][00:47.01]却被她全部抹杀
[02:15.96][00:48.87]越谈她越相信永远得不到回答
[02:19.57][00:52.49]到底她怎么想
[02:21.35][00:54.28]应该继续在这么
[02:23.37][00:56.36]还是说穿跑了吧
[02:26.89][00:59.80]找一个承认失恋的方法
[02:30.48][01:03.41]让心情好好地放个假
[02:34.14][01:07.00]当你我不小心又想起她
[02:45.69][02:42.20][02:37.69][01:10.60]就在记忆里画一个叉
[02:48.69]
[01:33.58]编辑:小婧
[01:43.33][00:16.27]她总是只留下电话号码
上面这行歌词表示:在 [00:16.27] 这个时间点播放 “她总是只留下电话号码” 这句歌词,
在 [01:43.33] 这个时间点再一个播放 “她总是只留下电话号码” 这句歌词。
其实可以把上面这行歌词拆分为下面两句歌词:
[00:16.27]她总是只留下电话号码
[01:43.33]她总是只留下电话号码
二、解析LRC歌词
1、读取出歌词文件
/**
* 从assets目录下读取歌词文件内容
* @param fileName
* @return
*/
public String getFromAssets(String fileName){
try {
InputStreamReader inputReader = new InputStreamReader( getResources().getAssets().open(fileName) );
BufferedReader bufReader = new BufferedReader(inputReader);
String line="";
String result="";
while((line = bufReader.readLine()) != null){
if(line.trim().equals(""))
continue;
result += line + "\r\n";
}
return result;
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
例如:从assets目录下读取test.lrc歌词文件内容,则可以调用上面的getFromAssets(String fileName)方法得到歌词的文本内容,如下所示:
String lrc = getFromAssets("test.lrc");
2、解析得到的歌词内容
1、表示每行歌词内容的实体类LrcRow
首先封装一个表示每行歌词内容的实体类LrcRow,该类由三个属性,分别为:
strTime、time、content。
strTime表示该行歌词要开始播放的时间,格式如下:[02:34.14]例如一行歌词内容为:[02:34.14]当你我不小心又想起她 , 解析该行歌词后的实体类LrcRow的属性如下所示:
time表示将strTime转换为long型之后的数值
例如将strTime为[02:34.14]格式转换154014(154014=02 * 60 * 1000 + 34 * 1000+14)
content表示该行歌词的内容,如:当你我不小心又想起她
代码如下:
package com.oyp.lrc.view.impl;