时间:2021-10-27 09:15:49 | 栏目:Android代码 | 点击:次
最近在做Android 的MP3播放的项目,要实现歌词的自动滚动,以及同步显示。
lyric的歌词解析主要用yoyoplayer里面的,显示部分参考了这里 ,这里只是模拟MP3歌词的滚动。
先上一下效果图:
滚动实现的代码其实也简单。显示画出当前时间点的歌词,然后再分别画出改歌词后面和前面的歌词,前面的部分往上推移,后面的部分往下推移,这样就保持了当前时间歌词在中间。
代码如下 LyricView,相关信息在注释了标明了。
package ru.org.piaozhiye.lyric; import java.io.File; import java.util.List; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Typeface; import android.util.AttributeSet; import android.widget.TextView; /** * @author root * */ public class LyricView extends TextView { private Paint mPaint; private float mX; private static Lyric mLyric; private Paint mPathPaint; public String test = "test"; public int index = 0; private List<Sentence> list; public float mTouchHistoryY; private int mY; private long currentDunringTime; // 当前行歌词持续的时间,用该时间来sleep private float middleY;// y轴中间 private static final int DY = 50; // 每一行的间隔 public LyricView(Context context) { super(context); init(); } public LyricView(Context context, AttributeSet attr) { super(context, attr); init(); } public LyricView(Context context, AttributeSet attr, int i) { super(context, attr, i); init(); } private void init() { setFocusable(true); PlayListItem pli = new PlayListItem("Because Of You", "/sdcard/MP3/Because Of You.mp3", 0L, true); mLyric = new Lyric(new File("/sdcard/MP3/Because Of You.lrc"), pli); list = mLyric.list; // 非高亮部分 mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setTextSize(22); mPaint.setColor(Color.WHITE); mPaint.setTypeface(Typeface.SERIF); // 高亮部分 当前歌词 mPathPaint = new Paint(); mPathPaint.setAntiAlias(true); mPathPaint.setColor(Color.RED); mPathPaint.setTextSize(22); mPathPaint.setTypeface(Typeface.SANS_SERIF); } protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(0xEFeffff); Paint p = mPaint; Paint p2 = mPathPaint; p.setTextAlign(Paint.Align.CENTER); if (index == -1) return; p2.setTextAlign(Paint.Align.CENTER); // 先画当前行,之后再画他的前面和后面,这样就保持当前行在中间的位置 canvas.drawText(list.get(index).getContent(), mX, middleY, p2); float tempY = middleY; // 画出本句之前的句子 for (int i = index - 1; i >= 0; i--) { // Sentence sen = list.get(i); // 向上推移 tempY = tempY - DY; if (tempY < 0) { break; } canvas.drawText(list.get(i).getContent(), mX, tempY, p); // canvas.translate(0, DY); } tempY = middleY; // 画出本句之后的句子 for (int i = index + 1; i < list.size(); i++) { // 往下推移 tempY = tempY + DY; if (tempY > mY) { break; } canvas.drawText(list.get(i).getContent(), mX, tempY, p); // canvas.translate(0, DY); } } protected void onSizeChanged(int w, int h, int ow, int oh) { super.onSizeChanged(w, h, ow, oh); mX = w * 0.5f; // remember the center of the screen mY = h; middleY = h * 0.5f; } // /** * @param time * 当前歌词的时间轴 * * @return currentDunringTime 歌词只需的时间 */ public long updateIndex(long time) { // 歌词序号 index = mLyric.getNowSentenceIndex(time); if (index == -1) return -1; Sentence sen = list.get(index); // 返回歌词持续的时间,在这段时间内sleep return currentDunringTime = sen.getDuring(); } }
剩下的就是使用他了。就是取出歌词的index,和该行歌词持续的时间进行sleep。
package ru.org.piaozhiye; import java.io.IOException; import ru.org.piaozhiye.lyric.LyricView; import android.app.Activity; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Handler; public class LyricDemo extends Activity { private MediaPlayer mp; private LyricView lyricView; private String path = "/sdcard/MP3/Because Of You.mp3"; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); lyricView = (LyricView) findViewById(R.id.audio_lrc); mp = new MediaPlayer(); mp.reset(); try { mp.setDataSource(path); mp.prepare(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } mp.start(); new Thread(new UIUpdateThread()).start(); } class UIUpdateThread implements Runnable { long time = 100; // 开始 的时间,不能为零,否则前面几句歌词没有显示出来 public void run() { while (mp.isPlaying()) { long sleeptime = lyricView.updateIndex(time); time += sleeptime; mHandler.post(mUpdateResults); if (sleeptime == -1) return; try { Thread.sleep(sleeptime); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } Handler mHandler = new Handler(); Runnable mUpdateResults = new Runnable() { public void run() { lyricView.invalidate(); // 更新视图 } }; }
整个project的源码。包括yoyoplayer的解析lyric部分代码。