最近在做一款android手机上的音乐播放器,学习到了很多东西,像是Fragment,ActionBar的使用等等,这里就先介绍一下歌词同步的实现问题。
歌词同步的实现思路很简单:获取歌词文件LRC中的时间和歌词内容,然后在指定的时间内播放相应的内容。获取不难,难就在于如何在手机屏幕上实现歌词的滚动。
先上效果图:
先从最基本的读取歌词文件开始:
Public class LrcHandle {
private List mWords = new ArrayList();
private List mTimeList = new ArrayList();
//处理歌词文件
public void readLRC(String path) {
File file = new File(path);
try {
FileInputStream fileInputStream = new FileInputStream(file);
InputStreamReader inputStreamReader = new InputStreamReader(
fileInputStream, utf-8
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader);
String s = ;
while ((s = bufferedReader.readLine()) != null) {
addTimeToList(s);
if ((s.indexOf([ar:) != -1) || (s.indexOf([ti:) != -1)
|| (s.indexOf([by:) != -1)) {
s = s.substring(s.indexOf(:) + 1, s.indexOf(]
} else {
String ss = s.substring(s.indexOf([), s.indexOf(]) + 1);
s = s.replace(ss, );
}
mWords.add(s);
}
bufferedReader.close();
inputStreamReader.close();
fileInputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
mWords.add(没有歌词文件,赶紧去下载
} catch (IOException e) {
e.printStackTrace();
mWords.add(没有读取到歌词
}
}
public List getWords() {
return mWords;
}
public List getTime() {
return mTimeList;
}
// 分离出时间
private int timeHandler(String string) {
string = string.replace(., :
String timeData[] = string.split(:
// 分离出分、秒并转换为整型
int minute = Integer.parseInt(timeData[0]);
int second = Integer.parseInt(timeData[1]);
int millisecond = Integer.parseInt(timeData[2]);
// 计算上一行与下一行的时间转换为毫秒数
int currentTime = (minute * 60 + second) * 1000 + millisecond * 10;
return currentTime;
}
private void addTimeToList(String string) {
Matcher matcher = pile(
[d{1,2}:d{1,2}([.:]d{1,2})?]).matcher(string);
if (matcher.find()) {
String str = matcher.group();
mTimeList.add(new LrcHandle().timeHandler(str.substring(1,
str.length() - 1)));
}
}
}
一般歌词文件的格式大概如下:
[ar:艺人名]
[ti:曲名]
[al:专辑名]
[by:编者(指编辑LRC歌词的人)]
[offset:时间补偿值] 其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢的。
但也不一定,有时候并没有前面那些ar:等标识符,所以我们这里也提供了另一种解析方式。
歌词文件中的时间格式则比较统一:[00:00.50]等等,00:表示分钟,00.表示秒数,.50表示毫秒数,当然,我们最后是要将它们转化为毫秒数处理才比较方便。