Android实现歌词滑动显示
16lz
2021-01-26
继承TextView自定义LyricView
import java.util.List; import com.anjoyo.musicplayer.bean.LyricBean; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.Shader; import android.graphics.Typeface; import android.graphics.Paint.Align; import android.graphics.Shader.TileMode; import android.util.AttributeSet; import android.widget.TextView; public class LyricView extends TextView { /** 控件的高 */ private float mHeight; /** 控件的宽 */ private float mWidth; private Paint mPaint; private Paint prePaint; private Paint nextPaint; /** 当前歌曲的歌词 */ private List lyricBeanList; /** 歌词进度,List中的位置 */ private int index; private float heightSign; private boolean start; private Shader inShader = new LinearGradient(0, 0, 0, LYRIC_ONE_HEIGHT, Color.argb(0xcc, 0xcc, 0xcc, 0xcc), Color.argb(0xff, 0xff, 0xff, 0xff), TileMode.MIRROR); private Shader outShader = new LinearGradient(0, LYRIC_ONE_HEIGHT, 0, 0, Color.argb(0xcc, 0xcc, 0xcc, 0xcc), Color.argb(0xff, 0xff, 0xff, 0xff), TileMode.MIRROR); /** 歌词显示的字体大小 */ private static final int LYRIC_TEXT_SIZE = 36; /** 每行歌词的高度 */ private static final int LYRIC_ONE_HEIGHT = 60; public LyricView(Context context) { super(context); initView(); } public LyricView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(); } public LyricView(Context context, AttributeSet attrs) { super(context, attrs); initView(); new UpdateThread().start(); } private void initView() { setFocusable(true); mPaint = new Paint(); mPaint.setAntiAlias(true);// 设置画笔的锯齿效果 mPaint.setTextAlign(Align.CENTER); mPaint.setTextSize(LYRIC_TEXT_SIZE); mPaint.setTypeface(Typeface.SERIF); prePaint = new Paint(mPaint); prePaint.setShader(outShader); nextPaint = new Paint(mPaint); nextPaint.setShader(inShader); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (canvas == null) { return; } mPaint.setColor(Color.argb(0xff, 0xff, 0xff, 0xff));//当前歌词词句颜色 if (lyricBeanList == null || lyricBeanList.size() < 1 || index > lyricBeanList.size() - 1) { canvas.drawText("好音质,MusicPlayer!", mWidth / 2, mHeight / 2, mPaint); return; } canvas.drawText(lyricBeanList.get(index).getLyric(), mWidth / 2, heightSign, mPaint); mPaint.setColor(Color.argb(0xcc, 0xcc, 0xcc, 0xcc));//非当前歌词词句颜色 float currentY = heightSign; //画出本句之前的歌词 for (int i = index - 1; i >= 0; i--) { currentY -= LYRIC_ONE_HEIGHT; if (i == index - 1) { canvas.drawText(lyricBeanList.get(i).getLyric(), mWidth / 2, currentY, prePaint); } else { canvas.drawText(lyricBeanList.get(i).getLyric(), mWidth / 2, currentY, mPaint); } } currentY = heightSign; //画出本句之后的歌词 for (int i = index + 1; i < lyricBeanList.size(); i++) { currentY += LYRIC_ONE_HEIGHT; if (i == index + 1) { canvas.drawText(lyricBeanList.get(i).getLyric(), mWidth / 2, currentY, nextPaint); } else { canvas.drawText(lyricBeanList.get(i).getLyric(), mWidth / 2, currentY, mPaint); } } } public void setLyricList(List lyricBeanList) { this.lyricBeanList = lyricBeanList; } public void setStart(boolean start) { this.start = start; } public boolean getStart() { return this.start; } public void setIndex(int index) { if (this.index != index) { this.index = index; heightSign = mHeight / 2 + LYRIC_ONE_HEIGHT / 2; } } private class UpdateThread extends Thread { @Override public void run() { while (true) { if (start && lyricBeanList.size() > index + 1) { if (heightSign > mHeight / 2f - LYRIC_ONE_HEIGHT / 2f) { heightSign -= LYRIC_ONE_HEIGHT / (float)(lyricBeanList.get(index + 1).getLyricTime() - lyricBeanList.get(index).getLyricTime()) * 50; } postInvalidate(); } try { sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth = w; mHeight = h; heightSign = h / 2f + LYRIC_ONE_HEIGHT / 2f; } }
LyricBean.java如下
import java.util.List; /** * 一句歌词 * * @author HLP */ public class LyricBean { /** 一句歌词 */ private String lyric; /** 本句歌词开始的时间 */ private int lyricTime; /** 本句歌词每个字的持续时间 ,构成数组 */ private List wordsTime; public LyricBean(String lyric, int lyricTime, List wordsTime) { super(); this.lyric = lyric; this.lyricTime = lyricTime; this.wordsTime = wordsTime; } public String getLyric() { return lyric; } public void setLyric(String lyric) { this.lyric = lyric; } public int getLyricTime() { return lyricTime; } public void setLyricTime(int lyricTime) { this.lyricTime = lyricTime; } public List getWordsTime() { return wordsTime; } public void setWordsTime(List wordsTime) { this.wordsTime = wordsTime; } }
有个模拟【天天动听】的项目在GitHub上,需要手机中有MP3歌曲和天天动听格式的歌词,
歌曲和歌词文件名一致,查看请点击
更多相关文章
- 动态生成控件
- Android(安卓)ArrayListAdapter泛型类
- Java - Android(安卓)自定义控件之圆形进度条
- Android画一个随意拖动的圆形
- android 自带的日期控件 DatePicker
- 自定义View组合模式
- [控件]SeekBar拖动条
- Android(安卓)UI控件-Spinner(下拉列表)
- android text 中英文混排 换行的问题