android编程实例-音乐播放器之歌词显示

来源:互联网 发布:服装cad软件有哪些 编辑:程序博客网 时间:2024/04/29 19:05

        今天分享一个歌词显示的项目,首先让我们来看看一般歌词是什么样的格式,就拿神曲《小苹果》来说的,请看歌词:

[00:00.91]小苹果[00:01.75]作词:王太利 作曲:王太利[00:02.47]演唱:筷子兄弟[00:03.32][00:17.40]我种下一颗种子[00:19.12]终于长出了果实[00:21.04]今天是个伟大日子[00:25.10]摘下星星送给你[00:26.79]拽下月亮送给你[00:28.77]让太阳每天为你升起[00:31.25][00:32.67]变成蜡烛燃烧自己[00:34.47]只为照亮你[00:36.44]把我一切都献给你[00:38.22]只要你欢喜[00:40.19]你让我每个明天都[00:42.15]变得有意义[00:44.04]生命虽短爱你永远[00:46.08]不离不弃[00:47.81][00:48.15]你是我的小呀小苹果儿[00:51.92]怎么爱你都不嫌多[00:55.26]红红的小脸儿温暖我的心窝[00:59.33]点亮我生命的火  火火火火[01:03.45]你是我的小呀小苹果儿[01:07.06]就像天边最美的云朵[01:10.61]春天又来到了花开满山坡[01:14.70]种下希望就会收获

新建一个java类Lyrc来表示歌词

public class Lyrc {public String lrcString;    //歌词public int sleepTime;     //一行歌词的持续时间public int timePoint;      //一行歌词结束的时间点}

新建java类对歌词进行处理,歌词中一行里有时间[00:48.15],用[ ]括起来,紧接着是歌词内容,我们一行一行的将歌词读入,并将时间和歌词分离。

public class LyrcUtil {private static List<Lyrc> lyrcList;/** * 读取歌词文件文件 * @param f * @return */public static List<Lyrc> readLRC(File f) {try {if (f == null || !f.exists()) {lyrcList = null;} else {lyrcList = new Vector<Lyrc>();InputStream is = new BufferedInputStream(new FileInputStream(f));BufferedReader br = new BufferedReader(new InputStreamReader(is, getCharset(f)));String strTemp = "";while ((strTemp = br.readLine()) != null) {strTemp = analyzeLRC(strTemp);}br.close();is.close();// 对歌词进行排序Collections.sort(lyrcList, new Sort());// 计算每行歌词的停留时间for (int i = 0; i < lyrcList.size(); i++) {Lyrc one = lyrcList.get(i);if (i + 1 < lyrcList.size()) {Lyrc two = lyrcList.get(i + 1);one.sleepTime = two.timePoint - one.timePoint;}}}} catch (Exception e) {e.printStackTrace();}return lyrcList;}/** * 处理歌词中的一行内容 *  * @param text * @return */private static String analyzeLRC(String text) {try {int pos1 = text.indexOf("[");int pos2 = text.indexOf("]");if (pos1 >= 0 && pos2 != -1) {Long time[] = new Long[getPossiblyTagCount(text)];time[0] = timeToLong(text.substring(pos1 + 1, pos2));if (time[0] == -1)return "";String strLineRemaining = text;int i = 1;while (pos1 >= 0 && pos2 != -1) {strLineRemaining = strLineRemaining.substring(pos2 + 1);pos1 = strLineRemaining.indexOf("[");pos2 = strLineRemaining.indexOf("]");if (pos2 != -1) {time[i] = timeToLong(strLineRemaining.substring(pos1 + 1, pos2));if (time[i] == -1)return ""; // LRCTexti++;}}Lyrc tl = null;for (int j = 0; j < time.length; j++) {if (time[j] != null) {tl = new Lyrc();tl.timePoint = time[j].intValue();tl.lrcString = strLineRemaining;lyrcList.add(tl);}}return strLineRemaining;} elsereturn "";} catch (Exception e) {return "";}}private static int getPossiblyTagCount(String Line) {String strCount1[] = Line.split("\\[");String strCount2[] = Line.split("\\]");if (strCount1.length == 0 && strCount2.length == 0)return 1;else if (strCount1.length > strCount2.length)return strCount1.length;elsereturn strCount2.length;}/** * 时间转换 *  * @param Time * @return */public static long timeToLong(String Time) {try {String[] s1 = Time.split(":");int min = Integer.parseInt(s1[0]);String[] s2 = s1[1].split("\\.");int sec = Integer.parseInt(s2[0]);int mill = 0;if (s2.length > 1)mill = Integer.parseInt(s2[1]);return min * 60 * 1000 + sec * 1000 + mill * 10;} catch (Exception e) {return -1;}}/** * 判断文件的编码类型 *  * @param file * @return */public static String getCharset(File file) {String charset = "GBK";byte[] first3Bytes = new byte[3];try {boolean checked = false;BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));bis.mark(0);int read = bis.read(first3Bytes, 0, 3);if (read == -1)return charset;if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) {charset = "UTF-16LE";checked = true;} else if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) {charset = "UTF-16BE";checked = true;} else if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB && first3Bytes[2] == (byte) 0xBF) {charset = "UTF-8";checked = true;}bis.reset();if (!checked) {int loc = 0;while ((read = bis.read()) != -1) {loc++;if (read >= 0xF0)break;if (0x80 <= read && read <= 0xBF)break;if (0xC0 <= read && read <= 0xDF) {read = bis.read();if (0x80 <= read && read <= 0xBF)continue;elsebreak;} else if (0xE0 <= read && read <= 0xEF) {read = bis.read();if (0x80 <= read && read <= 0xBF) {read = bis.read();if (0x80 <= read && read <= 0xBF) {charset = "UTF-8";break;} elsebreak;} elsebreak;}}}bis.close();} catch (Exception e) {e.printStackTrace();}return charset;}    //根据时间顺序进行排序private static class Sort implements Comparator<Lyrc> {public Sort() {}public int compare(Lyrc tl1, Lyrc tl2) {return sortUp(tl1, tl2);}private int sortUp(Lyrc tl1, Lyrc tl2) {if (tl1.timePoint < tl2.timePoint)return -1;else if (tl1.timePoint > tl2.timePoint)return 1;elsereturn 0;}}}

新建显示歌词的类LrcView

<pre name="code" class="java">public class LrcView extends TextView {private List<Lyrc> lyrcList;private int current = 0;// 行的间距private int lineSpacing = 30;// 当前正在绘制的行private Paint currentPaint;private int currentColor = Color.GREEN;private int currentSize = 18;private Typeface currentTypeface = Typeface.DEFAULT_BOLD;private Paint ortherPaint;private int ortherColor = Color.BLACK;private int ortherSize = 15;private Typeface ortherTypeface = Typeface.SERIF;private Handler handler = new Handler() {public void handleMessage(Message msg) {invalidate();  //重复onDraw()方法}};public LrcView(Context context, AttributeSet attrs) {super(context, attrs);lyrcList = LyrcUtil.readLRC(new File("/sdcard/小苹果.lrc"));currentPaint = new Paint();currentPaint.setColor(currentColor);currentPaint.setTextSize(currentSize);currentPaint.setTextAlign(Align.CENTER);currentPaint.setTypeface(currentTypeface);ortherPaint = new Paint();ortherPaint.setColor(ortherColor);ortherPaint.setTextSize(ortherSize);ortherPaint.setTextAlign(Align.CENTER);ortherPaint.setTypeface(ortherTypeface);}@Overrideprotected void onDraw(Canvas canvas) {// getWidth();// getHeight();if (current < lyrcList.size()) {if (lyrcList != null && lyrcList.size() > 0) {Lyrc lyrc =null;for (int i = current - 1; i >= 0; i--) {lyrc = lyrcList.get(i);canvas.drawText(lyrc.lrcString, getWidth() / 2, getHeight() / 2 + lineSpacing * (i - current), ortherPaint);}lyrc=lyrcList.get(current);canvas.drawText(lyrc.lrcString, getWidth() / 2, getHeight() / 2, currentPaint);for (int i = current + 1; i < lyrcList.size(); i++) {lyrc = lyrcList.get(i);canvas.drawText(lyrc.lrcString, getWidth() / 2, getHeight() / 2 + lineSpacing * (i - current), ortherPaint);}lyrc=lyrcList.get(current);handler.sendEmptyMessageDelayed(10, lyrc.sleepTime);current++;} else {canvas.drawText("未找到歌词", getWidth() / 2, getHeight() / 2, currentPaint);}}super.onDraw(canvas);}}

在res/layout下建立一个activity_main.xml,将LrcView 包含进来

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity" >    <com.zhuzhu.LrcView        android:id="@+id/lrcview"        android:layout_width="match_parent"        android:layout_height="match_parent" /></RelativeLayout>

在Activity中进行显示

public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}}



0 0
原创粉丝点击