Android(安卓)歌词Lrc显示 自定义View
16lz
2021-12-04
package com.louisgeek.louisappbase.custom;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import com.louisgeek.checkappupdatelib.tool.HttpTool;import com.louisgeek.louisappbase.musicplayer.LrcHelper;import com.louisgeek.louisappbase.musicplayer.bean.LrcLineBean;import com.louisgeek.louisappbase.util.FileTool;import com.louisgeek.louisappbase.util.RawUtil;import com.socks.library.KLog;import java.util.ArrayList;import java.util.List;/** * Created by louisgeek on 2016/11/26. */public class KooLrcView extends View { private Context mContext; private Paint mPaint; private List mLrcAllLineBeanList=new ArrayList<>(); private int mNowPlayLinePos; private float mTextHeight; private float mAnimateChangeY; private int mViewWidth, mViewHeight; private float mTextCenterY;//baseline和文字中线的偏移 0,0时 就是y private float mTextLineDis = 20;//行距 private float mHighLightTextCenterY;//画高亮文字的起始Y private float mTextSize = 35; private int mNormalTextColor = Color.GRAY; private int mHighLightTextColor = Color.GREEN; private int mUpOrDownViewCanDrawLines;// public KooLrcView(Context context) { this(context, null); } public KooLrcView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public KooLrcView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; initView(); } private void initView() { mPaint = new Paint(); mPaint.setTextSize(mTextSize); mPaint.setAntiAlias(true); mPaint.setDither(true); setLrcStr_FileUrl("https://code.aliyun.com/hi31588535/outside_chain/raw/master/xzq_yy.lrc"); //获取文字的高度 向上取整 mTextHeight = (float) Math.ceil(mPaint.descent() - mPaint.ascent()); /* Paint.FontMetrics fontMetrics=mPaint.getFontMetrics(); float fontSpacing =mPaint.getFontSpacing(); float textHeight2 = (float) Math.ceil(fontMetrics.descent - fontMetrics.ascent);*/ KLog.d("mTextHeight" + mTextHeight); /** * baseline和文字中线的偏移 0,0时 就是y */ mTextCenterY = mTextHeight / 2 - mPaint.descent(); // handler.post(runnable);//启动歌词滚动 } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width = resolveSize(widthSize, widthMeasureSpec); int height = resolveSize(heightSize, heightMeasureSpec); mViewWidth = width; mViewHeight = height; KLog.d("mViewWidth:" + mViewWidth); KLog.d("mViewHeight:" + mViewHeight); mHighLightTextCenterY = mViewHeight / 2; float temp = mViewHeight - mTextHeight;//减去中间一行 mUpOrDownViewCanDrawLines = (int) Math.ceil(temp / 2 / (mTextHeight + mTextLineDis)); KLog.d("mUpOrDownViewCanDrawLines" + mUpOrDownViewCanDrawLines); mUpOrDownViewCanDrawLines = mUpOrDownViewCanDrawLines + 1;//多画一行 // setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /* int screenWidth = mContext.getResources().getDisplayMetrics().widthPixels; int screenHeight = mContext.getResources().getDisplayMetrics().heightPixels;*/ canvas.translate(mViewWidth / 2, mHighLightTextCenterY); mPaint.setStrokeWidth(2); mPaint.setColor(Color.RED); /** * 参考中线 */ //#### canvas.drawLine(-mViewWidth / 2, 0, mViewHeight / 2, 0, mPaint); /** * */ String testText = "暂无歌词"; // Rect rectOut = new Rect(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.BLUE); mPaint.getTextBounds(testText, 0, testText.length(), rectOut); // Rect rectNew = new Rect(-mViewWidth / 2, (int) (rectOut.top + mTextCenterY), mViewWidth / 2, (int) (rectOut.bottom + mTextCenterY)); /** * 参考框 */ //### canvas.drawRect(rectNew, mPaint); mPaint.setTextSize(mTextSize); mPaint.setTextAlign(Paint.Align.CENTER); mPaint.setStyle(Paint.Style.FILL); if (mLrcAllLineBeanList.size()<=0){ mPaint.setColor(Color.GREEN); canvas.drawText(testText,0, 0 + mTextCenterY,mPaint); return; } //KLog.d("mNowPlayLinePos:"+mNowPlayLinePos); for (int i = 0; i < mLrcAllLineBeanList.size(); i++) { // String textContent = mLrcAllLineBeanList.get(i).getContent(); //画 正在播放的行 if (i == mNowPlayLinePos) { mPaint.setColor(mHighLightTextColor); canvas.drawText(textContent, 0, 0 + mTextCenterY - mAnimateChangeY, mPaint); } else if (i < mNowPlayLinePos) { //上面的行 /* if ((mNowPlayLinePos - i) > mUpOrDownViewCanDrawLines) { continue; }*/ mPaint.setColor(mNormalTextColor); canvas.drawText(textContent, 0, 0 - (mTextHeight + mTextLineDis) * (mNowPlayLinePos - i) + mTextCenterY - mAnimateChangeY, mPaint); } else { //下面的行 /* if ((i - mNowPlayLinePos) > mUpOrDownViewCanDrawLines) { continue; }*/ mPaint.setColor(mNormalTextColor); canvas.drawText(textContent, 0, 0 + (mTextHeight + mTextLineDis) * (i - mNowPlayLinePos) + mTextCenterY - mAnimateChangeY, mPaint); } } } //millisecond是定时器传过来的 会调用很多次 值一直在变 private int mLastSaveTempI = -1; public void setTimeMillisecond(int millisecond) { //KLog.d("zfq millisecond:" + millisecond); long LeftTime; long rightTime; long duation; for (int i = 0; i < mLrcAllLineBeanList.size(); i++) { if (i == 0) { LeftTime = 0; rightTime = mLrcAllLineBeanList.get(i).getTimeMillisecond(); } else { LeftTime = mLrcAllLineBeanList.get(i - 1).getTimeMillisecond(); rightTime = mLrcAllLineBeanList.get(i).getTimeMillisecond(); } //确定是第几句 if (millisecond >= LeftTime && millisecond < rightTime) { // millisecond是定时器传过来的 会调用很多次 所以要处理 if (mLastSaveTempI != i) { duation = rightTime - LeftTime; nextLine(i, duation); /// mLastSaveTempI = i; KLog.d("mLastSaveTempI:" + mLastSaveTempI); } break; } } } private ValueAnimator valueAnimator; public void nextLine(final int nextLinePos, long duration) { KLog.d("nextLineCxq mNowPlayLinePos:" + nextLinePos); if (nextLinePos == mNowPlayLinePos) { return; } if (valueAnimator != null && valueAnimator.isRunning()) { valueAnimator.end(); } /** * 播放到最后一行歌词 固定 不需要动画了 */ if (mNowPlayLinePos < mLrcAllLineBeanList.size() - 1) { /** * 向上切换一行动画 */ valueAnimator = ValueAnimator.ofFloat(0.0f, mTextHeight + mTextLineDis).setDuration(duration); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { // 0~mTextHeight + mTextLineDis 0~一行的高度 mAnimateChangeY = (float) animation.getAnimatedValue(); // KLog.d("mAnimateChangeY:" + mAnimateChangeY); if (mAnimateChangeY == 0) { KLog.d("nextLineC start" + System.currentTimeMillis()); /* do nothing */ } else if (mAnimateChangeY < (mTextHeight + mTextLineDis)) {//逐渐位移1行 invalidate(); } else if (mAnimateChangeY == (mTextHeight + mTextLineDis)) { //位移1行结束时候 mAnimateChangeY = 0;// 当前行停顿 切换下一行 不改变上下Y 重新绘制 //下一行 mNowPlayLinePos = nextLinePos; // mNowPlayLinePos++; invalidate();//只改变下一行颜色 KLog.d("nextLineC end" + System.currentTimeMillis()); } } }); valueAnimator.start(); } } /** * * @param lrcFileUrl https://code.aliyun.com/hi31588535/outside_chain/raw/master/xzq_yy.lrc */ public void setLrcStr_FileUrl(String lrcFileUrl) { HttpTool.getUrlBackString(lrcFileUrl, new HttpTool.OnUrlBackStringCallBack() { @Override public void onSuccess(final String backStr) { setLrcStr(backStr); } @Override public void onError(String errorMsg) { } }); } /** * * @param lrcFilePath /storage/emulated/0/Download/xzqyy.lrc */ public void setLrcStr_FilePath(String lrcFilePath) { String lrcStr =FileTool.getFileContentWithRN(lrcFilePath); setLrcStr(lrcStr); } public void setLrcStr_FileRawID(int lrcFileRawID) { String lrcStr = RawUtil.getStringFromRawWithRN(mContext, lrcFileRawID); setLrcStr(lrcStr); } public void setLrcStr(String lrcStr) { mLrcAllLineBeanList.clear(); mLrcAllLineBeanList = LrcHelper.parseAllLrc(lrcStr); invalidate(); } @Override public boolean onTouchEvent(MotionEvent event) { float startX, startY; int action = event.getAction();// KLog.d("action:" + action); switch (action) { case MotionEvent.ACTION_DOWN: startX = event.getX(); startY = event.getY(); break; case MotionEvent.ACTION_MOVE: // mHighLightTextCenterY = event.getY(); KLog.d("mHighLightTextCenterY:" + mHighLightTextCenterY); // invalidate(); break; case MotionEvent.ACTION_UP: break; } return super.onTouchEvent(event); }}
更多相关文章
- android 复制、粘贴文字
- android 按钮按下效果(文字颜色和按钮同时变化)
- Android(安卓)RadioButton 文字在左边
- Android开发―利用FrameLayout实现图标中间显示文字
- 设置TextView文字居中
- Android手机开发 控件 TextView文字居中
- Android(安卓)实现气泡布局/弹窗,可控制气泡尖角方向及偏移量
- Android之系统自带的文字外观设置及实际显示效果图 android:text
- TabLayout绑定Viewpager后不显示文字