最近在做Android 的MP3播放的项目,要实现歌词的自动滚动,以及同步显示。
lyric的歌词解析主要用yoyoplayer里面的,显示部分参考了这里 ,这里只是模拟MP3歌词的滚动。
先上一下效果图:
滚动实现的代码其实也简单。显示画出当前时间点的歌词,然后再分别画出改歌词后面和前面的歌词,前面的部分往上推移,后面的部分往下推移,这样就保持了当前时间歌词在中间。
代码如下 LyricView,相关信息在注释了标明了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
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。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
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部分代码。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/javaxinkule/article/details/53224896