哎,敢接触这个东西,看了好些东西,才明白,其中,借鉴如下这位网友:http://www.cnblogs.com/wenjiang/archive/2013/05/06/3063259.html?utm_source=tuicool
但还是看得很难懂:后来终于搞明白了,特简单易懂地写下来。
首先,如果解析lrc歌词文件:有些歌词是一句接着一句按时间顺序排列好的,但是有些事重复的没有顺序排列的,如下:
[00:00.00]午夜怨曲
[00:09.00]词 \ 叶世荣. 曲 \ 黄家驹. 主唱 \ 黄家驹.
[00:18.00]
[00:27.00]从来不知想拥有多少的理想
[00:33.00]还离不开种种困忧
[00:40.00]勉强去掩饰失意的感觉
[00:46.00]再次听到昨日的冷嘲
[00:52.00]徘徊於街中恐怕只得孤独
[00:58.00]寻回思忆中的碎片
[01:05.00]变作了一堆草芥风中散
[01:11.00]与你奏过午夜的怨曲
[04:12.00][03:47.00][03:22.00][02:19.00][01:16.00]总有挫折打碎我的心
[04:16.00][03:51.00][03:25.00][02:22.00][01:19.00]紧抱过去抑压了的手
[04:20.00][03:55.00][03:30.00][02:27.00][01:23.00]我与你也彼此一起艰苦过
[04:00.00][03:35.00][02:32.00][01:28.00]写上每句冰冷冷的诗
[04:03.00][03:38.00][02:35.00][01:31.00]不会放弃高唱这首歌
[04:07.00][03:42.00][02:39.00][01:36.00]我与你也彼此真的相识过
[01:55.00]从回忆中找不到天真的笑声
[02:01.00]曾留不低心中斗争
[02:08.00]每次去担当失意的主角
[02:14.00]冷笑变作故事的作者
[03:11.00]啊......啊......障碍能撕破
[04:25.00]
[04:27.00]BEYOND再见理想
[04:29.00]/~byfaith
但是解析也是差不多而已,只不过,找个稍微多用力一点点,
首选,建立一个map存放上面的有时间的内容;开头这些信息也没什么用,另放一个,有用则用,没用则不用;因为map存放时无序的,于是乎建立一个数组存放把key排序好的时间数组:
<span style="white-space:pre"> </span>//存放开头那些没有时间的信息
private List<String> info = new ArrayList<String>();
//存放有时间的歌词
private Map<String, String> lrcs = new Hashtable<String, String>();
//存放按照从小到大排序好的时间信息
private Object[] arr;
然后写一个主要运用indexof、substring来截取文本的方法:
//获取歌词,放进集合中
public void decodeLrc(String str) {
if (str.startsWith("[ti:")) {
info.add(str.substring(4, str.lastIndexOf("]")));
} else if (str.startsWith("[ar:")) {
info.add(str.substring(4, str.lastIndexOf("]")));
} else if (str.startsWith("[al:")) {
info.add(str.substring(4, str.lastIndexOf("]")));
} else if (str.startsWith("[la:")) {
info.add(str.substring(4, str.lastIndexOf("]")));
} else if (str.startsWith("[by:")) {
info.add(str.substring(4, str.lastIndexOf("]")));
} else {
//这里获取歌词信息
int startIndex;
int tempIndex = -1;
//获取多个中括号的相同歌词的信息
while ((startIndex = str.indexOf("[", tempIndex + 1)) != -1) {
int endIndex = str.indexOf("]", tempIndex + 1);
String tempTime = str.substring(tempIndex + 2, endIndex);
lrcs.put(tempTime, str.substring(str.lastIndexOf("]") + 1, str.length()));
tempIndex = endIndex;
}
}
}
通过上面这个方法,就把数据各自存放好了。接着写一个把hashtable的key键,也就是“时间”排序好,存放于arr数组中
<span style="white-space:pre"> </span>//把hashtable转为有秩序的组合
public void convertArrays() {
arr = lrcs.keySet().toArray();
Arrays.sort(arr);
}
================================================================================================================================
以上就是从lrc文件中获取歌词信息的内容。但往回看,如果读取lrc内,这样也就是一个方法:通过这个方法读取文件,然后再用上面的解析......
private void getLrcs(InputStreamReader isr) {
try {
BufferedReader reader = new BufferedReader(isr);
String line = "";
while ((line = reader.readLine()) != null) {
//一行一行读取,到方法中去解析信息
decodeLrc(line);
}
//key键的时间排序、组合
convertArrays();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
===========================================================================================================
歌词信息准备好了,接着就是写一个自定义的View来显示歌词同步,这个原理大概就是这样的:假设mediaplyaer传过来的时间是X,好了,我们把上面数组中的时间转为long型,假设第一句高亮歌词是Y,和这个X作比较,如果X大于或者等于Y,那么我们就开始显示下一行的高亮(上面已经做了歌词的排序是吧),通过重绘更新UI。
整个View的代码如下:
package china.testwt; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Typeface; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View; import java.io.*; import java.util.*; public class MyView extends View { private int mBgCol, mCurTextCol, mNorTextCol; private int mCurrentTextSize, mNormalTextSize; //存放开头那些没有时间的信息 private List<String> info = new ArrayList<String>(); //存放有时间的歌词 private Map<String, String> lrcs = new Hashtable<String, String>(); //存放按照从小到大排序好的时间信息 private Object[] arr; //不高亮的歌词画笔 private Paint mLoseFocusPaint; //高亮的 private Paint mOnFocusePaint; //一行歌词的开始位置X private float drawTextX = 0; //Y private float drawTextY = 0; //整个View的高 private float viewHeight = 0; //间隔,移动的大小 private int mSpacing; //高亮的行数 private int mIndex = 0; //获取数据源,接口 public void setLrcSource(FileInputStream reader) { InputStreamReader isr = new InputStreamReader(reader); getLrcs(isr); } //获取当前行位置,接口 public void setLrcPostion(long position) { if (mIndex < lrcs.size()) { long tmepPos = parseTime(arr[mIndex].toString()); if (tmepPos < position) { //更新UI postInvalidate();