Runt
2022-05-04 7f292c4158e1854ca6dc72895c829e538cbc6c7b
app/src/main/java/com/auto/lyric/widgets/LyricView.java
@@ -1,151 +1,200 @@
package com.auto.lyric.widgets;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
import android.widget.TextView;
import android.util.Log;
import com.auto.lyric.R;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.auto.lyric.data.LyricObject;
import com.auto.lyric.data.LyricServer;
import com.auto.lyric.util.DeviceUtil;
/**
 * 歌词
 * Created by Runt (qingingrunt2010@qq.com) on 2022/4/30.
 */
public class LyricView extends androidx.appcompat.widget.AppCompatTextView {
    private Paint mPaint;
    private float mX;
    private Paint mPathPaint;
    public int index = 0;
    private List<Sentence>  list;
    public float mTouchHistoryY;
    private int mY;
    private float middleY;//
    private static final int DY = 40; //
    public LyricView(Context context) {
    private float mX;       //屏幕X轴的中点,此值固定,保持歌词在X中间显示
    private float offsetY;      //歌词在Y轴上的偏移量,此值会根据歌词的滚动变小
    private int lrcIndex=0; //保存歌词TreeMap的下标
    private  int SIZEWORD=0;//显示歌词文字的大小值
    private  int INTERVAL=45;//歌词每行的间隔
    Paint paint=new Paint();//画笔,用于画不是高亮的歌词
    Paint paintHL=new Paint();  //画笔,用于画高亮的歌词,即当前唱到这句歌词
    public LyricView(Context context){
        super(context);
        init();
    }
    public LyricView(Context context, AttributeSet attr) {
        super(context, attr);
    public LyricView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    public LyricView(Context context, AttributeSet attr, int i) {
        super(context, attr, i);
        init();
    }
    private void init() {
        setFocusable(true);
        if(list==null){
            list=new ArrayList<Sentence>();
            Sentence sen=new Sentence(0," ");
            list.add(0, sen);
        }
        //
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(24);
        mPaint.setColor(Color.BLACK);
        mPaint.setAlpha(80);
        mPaint.setTypeface(Typeface.SERIF);
        //
        mPathPaint = new Paint();
        mPathPaint.setAntiAlias(true);
        mPathPaint.setColor(Color.RED);
        mPathPaint.setTextSize(24);
        mPathPaint.setTypeface(Typeface.SANS_SERIF);
    }
    /* (non-Javadoc)
     * @see android.view.View#onDraw(android.graphics.Canvas)
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(0xEFeffff);
        Paint p = mPaint;
        Paint p2 = mPathPaint;
        p.setTextAlign(Paint.Align.LEFT);
        if (index == -1)
            return;
        p2.setTextAlign(Paint.Align.LEFT);
        //
        canvas.drawText(list.get(index).getName(), mX, middleY, p2);
        float tempY = middleY;
        //
        for (int i = index - 1; i  >= 0; i--) {
            tempY = tempY - DY;
            if (tempY < 0) {
                break;
            }
            canvas.drawText(list.get(i).getName(), mX, tempY, p);
        }
        tempY = middleY;
        //
        for (int i = index + 1; i < list.size(); i++) {
            //
            tempY = tempY + DY;
            if (tempY  > mY) {
                break;
            }
            canvas.drawText(list.get(i).getName(), mX, tempY, p);
        }
    }
    protected void onSizeChanged(int w, int h, int ow, int oh) {
        super.onSizeChanged(w, h, ow, oh);
        mX = w * 0.3f;
        mY = h;
        middleY = h * 0.5f;
    }
    public long updateIndex(int index) {
        if (index == -1)
            return -1;
        this.index=index;
        return index;
    }
    public List<Sentence>  getList() {
        return list;
    }
    public void setList(List<Sentence>  list) {
        this.list = list;
    }
    public void updateUI(){
        new Thread(new updateThread()).start();
    }
    class updateThread implements Runnable {
        long time = 300;
        int i=0;
        public void run() {
            while (true) {
                long sleeptime = updateIndex(i);
                time += sleeptime;
                mHandler.post(mUpdateResults);
                if (sleeptime == -1)
                    return;
                try {
                    Thread.sleep(time);
                    i++;
                    if(i==getList().size())
                    {
                        i=0;
                        time = 300;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
        if(LyricServer.getLrc_map().size() > 0){
            paintHL.setTextSize(SIZEWORD);
            paint.setTextSize(SIZEWORD);
            LyricObject temp= LyricServer.getLrc_map().get(lrcIndex);
            canvas.drawText(temp.lrc, mX, offsetY+(SIZEWORD+INTERVAL)*lrcIndex, paintHL);
            // 画当前歌词之前的歌词
            for(int i=lrcIndex-1;i>=0;i--){
                temp=LyricServer.getLrc_map().get(i);
                if(offsetY+(SIZEWORD+INTERVAL)*i<0){
                    break;
                }
                canvas.drawText(temp.lrc, mX, offsetY+(SIZEWORD+INTERVAL)*i, paint);
            }
            // 画当前歌词之后的歌词
            for(int i=lrcIndex+1;i<LyricServer.getLrc_map().size();i++){
                temp=LyricServer.getLrc_map().get(i);
                if(offsetY+(SIZEWORD+INTERVAL)*i>600){
                    break;
                }
                canvas.drawText(temp.lrc, mX, offsetY+(SIZEWORD+INTERVAL)*i, paint);
            }
        }
    }
    Handler mHandler = new Handler();
    Runnable mUpdateResults = new Runnable() {
        public void run() {
            invalidate(); //
        else{
            paint.setTextSize(25);
            canvas.drawText("找不到歌词", mX, 310, paint);
        }
    };
        super.onDraw(canvas);
    }
    public void init(){
        offsetY=320;
        paint=new Paint();
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setColor(Color.GREEN);
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setAlpha(180);
        paintHL=new Paint();
        paintHL.setTextAlign(Paint.Align.CENTER);
        paintHL.setColor(Color.RED);
        paintHL.setAntiAlias(true);
        paintHL.setAlpha(255);
    }
    /**
     * 根据歌词里面最长的那句来确定歌词字体的大小
     */
    public void setTextSize(){
        if(LyricServer.getLrc_map().size() == 0){
            return;
        }
        int max=LyricServer.getLrc_map().get(0).lrc.length();
        for(int i=1;i<LyricServer.getLrc_map().size();i++){
            LyricObject lrcStrLength=LyricServer.getLrc_map().get(i);
            if(max<lrcStrLength.lrc.length()){
                max=lrcStrLength.lrc.length();
            }
        }
        SIZEWORD = DeviceUtil.convertDpToPixel(320/max,getContext());
    }
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mX = w * 0.5f;
        super.onSizeChanged(w, h, oldw, oldh);
    }
    /**
     *  歌词滚动的速度
     *
     * @return 返回歌词滚动的速度
     */
    public Float SpeedLrc(){
        float speed=0;
        if(offsetY+(SIZEWORD+INTERVAL)*lrcIndex>220){
            speed=((offsetY+(SIZEWORD+INTERVAL)*lrcIndex-220)/20);
        } else if(offsetY+(SIZEWORD+INTERVAL)*lrcIndex < 120){
            Log.i("speed", "speed is too fast!!!");
            speed = 0;
        }
        //      if(speed<0.2){
        //          speed=0.2f;
        //      }
        return speed;
    }
    /**
     * 按当前的歌曲的播放时间,从歌词里面获得那一句
     * @param time 当前歌曲的播放时间
     * @return 返回当前歌词的索引值
     */
    public int getIndex(int time){
        int index=0;
        for(int i=0;i<LyricServer.getLrc_map().size();i++){
            LyricObject temp=LyricServer.getLrc_map().get(i);
            if(temp.begintime<time){
                ++index;
            }
        }
        lrcIndex = index-1;
        if(lrcIndex<0){
            lrcIndex=0;
        }
        return lrcIndex;
    }
    public void setIndex(int lrcIndex) {
        this.lrcIndex = lrcIndex;
    }
    /**
     * @return the offsetY
     */
    public float getOffsetY() {
        return offsetY;
    }
    /**
     * @param offsetY the offsetY to set
     */
    public void setOffsetY(float offsetY) {
        this.offsetY = offsetY;
    }
    /**
     * @return 返回歌词文字的大小
     */
    public int getSIZEWORD() {
        return SIZEWORD;
    }
    /**
     * 设置歌词文字的大小
     * @param sIZEWORD the sIZEWORD to set
     */
    public void setSIZEWORD(int sIZEWORD) {
        SIZEWORD = sIZEWORD;
    }
    public int getIndexFromOffsetY(float offsetY){
        //220 - index * (binding.lyric.getSIZEWORD() + 44)
        int index = (int) ((220 - offsetY) / (SIZEWORD + 44));
        Log.i("LyricView", "getIndexFromOffsetY index:"+index);
        if(index < 0){
            return 0;
        }else if(LyricServer.getLrc_map().keySet().size()>index){
            return index;
        }else {
            return LyricServer.getLrc_map().keySet().size() -1;
        }
    }
}