手机影音项目笔记(四)---音乐播放歌词的控件的自定义

来源:互联网 发布:微信公众java开发 编辑:程序博客网 时间:2024/04/27 23:27
LyricsView
public class LyricsView extends TextView {    private Paint mPaint;    private int HIGHLIGHTT_COLOR;    private int NORMAL_COLOR;    private int HIGHLIGHT_SIZE;    private int NORMMAL_SIZE;    private int mViewW;    private int mViewH;    private ArrayList<Lyric> lyricArrayList;    private int centerIndex;    private int LINE_HEIGHT;    private int mDuration;    private int mPosition;    public LyricsView(Context context) {        super(context);        initView();    }    public LyricsView(Context context, AttributeSet attrs) {        super(context, attrs);        initView();    }    public LyricsView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initView();    }    private void initView() {        HIGHLIGHT_SIZE = getResources().getDimensionPixelSize(R.dimen.hightlight_size);        NORMMAL_SIZE = getResources().getDimensionPixelSize(R.dimen.normal_size);        LINE_HEIGHT = getResources().getDimensionPixelSize(R.dimen.line_height);        HIGHLIGHTT_COLOR = Color.GREEN;        NORMAL_COLOR = Color.WHITE;        mPaint = new Paint();        mPaint.setAntiAlias(true);        mPaint.setColor(HIGHLIGHTT_COLOR);        mPaint.setTextSize(HIGHLIGHT_SIZE);        // 伪造歌词数据//        lyricArrayList = new ArrayList<>();//        for (int i = 0; i < 30; i++) {//            lyricArrayList.add(new Lyric(i * 2000,"当前歌词的行数为:"+i));//        }//        centerIndex = 16;    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mViewW = w;        mViewH = h;    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (lyricArrayList == null || lyricArrayList.size() == 0) {            drawSingleLineText(canvas);        } else {            drawMuliteLineText(canvas);        }    }    private void drawMuliteLineText(Canvas canvas) {        // 获取据中行的歌词        Lyric lyric = lyricArrayList.get(centerIndex);//        移动的距离 = 已消耗时间百分比 * 行高//        已消耗时间百分比 = 已消耗时间 / 可用时间//        已消耗时间 = 当前播放进度 - 行起始时间//        可用时间 = 下一行起始时间 - 行起始时间        // 下一行起始时间        int nextStartPoint ;        if (centerIndex != lyricArrayList.size()-1){            // 非最后一行            Lyric nextLyric = lyricArrayList.get(centerIndex + 1);            nextStartPoint = nextLyric.getStartPoint();        }else{            // 最后一行            nextStartPoint = mDuration;        }        // 可用时间        int lineTime = nextStartPoint - lyric.getStartPoint();        // 已消耗时间        int pastTime = mPosition - lyric.getStartPoint();        // 已消耗时间百分比        float pastPercent = pastTime / (float)lineTime;        // 移动的距离        float offsetY = pastPercent * LINE_HEIGHT;        // 计算居中行的Y位置        // 获取文本宽高        Rect bounds = new Rect();        mPaint.getTextBounds(lyric.getContent(),0,lyric.getContent().length(),bounds);        // 计算居中行的Y坐标        float centerY = mViewH / 2 + bounds.height() / 2 - offsetY;        for (int i = 0; i < lyricArrayList.size(); i++) {            if (i!=centerIndex){                // 不是居中行                mPaint.setColor(NORMAL_COLOR);                mPaint.setTextSize(NORMMAL_SIZE);            }else{                // 居中行                mPaint.setColor(HIGHLIGHTT_COLOR);                mPaint.setTextSize(HIGHLIGHT_SIZE);            }            Lyric drawLyric = lyricArrayList.get(i);            // centerY + lineH * (drawIndex - centerIndex)            float drawY = centerY + LINE_HEIGHT * (i - centerIndex);            drawHorizontalText(canvas, drawLyric.getContent(), drawY);        }    }    private void drawHorizontalText(Canvas canvas, String text, float drawY) {        // 获取文本宽高        Rect bounds = new Rect();        mPaint.getTextBounds(text,0,text.length(),bounds);        // 计算绘制文本的坐标        float drawX = mViewW / 2 - bounds.width() / 2;        canvas.drawText(text, drawX, drawY, mPaint);    }    private void drawSingleLineText(Canvas canvas) {        String text = "正在加载歌词...";//        X = view宽度的一半 - 文本宽度的一半//        Y = view高度的一半 + 文本高度的一半        // 获取文本宽高        Rect bounds = new Rect();        mPaint.getTextBounds(text,0,text.length(),bounds);        // 计算绘制文本的坐标        float drawX = mViewW / 2 - bounds.width() / 2;        float drawY = mViewH / 2 + bounds.height() / 2;        canvas.drawText(text, drawX, drawY, mPaint);    }    // 根据当前歌曲的播放进度,更新居中行的位置    public void computeCenterIndex(int position,int duration){        mPosition = position;        mDuration = duration;        // 比较所有行的起始时间,如果比较行的时间比播放时间小,并且下一行的时间比播放时间大        for (int i = 0; i < lyricArrayList.size(); i++) {            Lyric lyric = lyricArrayList.get(i);            int nextStartPoint;            if (i!=lyricArrayList.size()-1){                // 不是最后一行歌词                Lyric nextLyric = lyricArrayList.get(i + 1);                nextStartPoint = nextLyric.getStartPoint();            }else{                nextStartPoint = duration;            }            if (lyric.getStartPoint() <= position && nextStartPoint > position){                centerIndex = i;                break;            }        }        invalidate();    }    // 更新歌词文件    public void setLyricsFile(File lyricsFile){        lyricArrayList = LyricsParser.parserFromFile(lyricsFile);        centerIndex = 0;    }}
LyricsLoader
public class LyricsLoader {    private static final File ROOT = new File(Environment.getExternalStorageDirectory(),"Download/audio");    // 根据指定的歌曲名,加载到对应的歌词文件    public static File loadFile(String title){        File file = new File(ROOT,title+".lrc");        if (file.exists()){            return  file;        }        file = new File(ROOT, title+".txt");        if (file.exists()){            return file;        }        // 到专门存放歌词的文件夹查找        //...        // 连接服务器下载歌词文件        // ...        return null;    }}
LyricsParser
public class LyricsParser {    // 从文件解析出歌词数据列表    public static ArrayList<Lyric> parserFromFile(File lyricsFile){        ArrayList<Lyric> lyrics = new ArrayList<>();        // 数据可用性验证        if (lyricsFile == null || !lyricsFile.exists()) {            lyrics.add(new Lyric(0, "无法解析歌词文件"));            return lyrics;        }        // 按行读取歌词并解析        try {            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(lyricsFile),"GBK"));            String line ;            while ((line= br.readLine())!=null){                // [01:22.04][02:35.04]寂寞的夜和谁说话                ArrayList<Lyric> lineLyrics = parserLine(line);                lyrics.addAll(lineLyrics);            }        } catch (Exception e) {            e.printStackTrace();        }        Collections.sort(lyrics);        return lyrics;    }    // 解析一行歌词 [01:22.04][02:35.04]寂寞的夜和谁说话    private static ArrayList<Lyric> parserLine(String line) {        ArrayList<Lyric> lineLyrics = new ArrayList<>();        String[] splitArr = line.split("]");        // [01:22.04 [02:35.04 寂寞的夜和谁说话        String content = splitArr[splitArr.length-1];        // [01:22.04 [02:35.04        for (int i = 0; i < splitArr.length - 1; i++) {            int startPoint = parserStartPoint(splitArr[i]);            lineLyrics.add(new Lyric(startPoint,content));        }        return lineLyrics;    }    // 解析歌词起始时间 [02:35.04    private static int parserStartPoint(String time) {        String[] splitArr = time.split(":");        // [02 35.04        String minStr = splitArr[0].substring(1);        // 35.04        String[] split = splitArr[1].split("\\.");        // 35 04        String secStr = split[0];        String msecStr = split[1];        // 将字符串转换为数值        int min = Integer.parseInt(minStr);        int sec = Integer.parseInt(secStr);        int msec = Integer.parseInt(msecStr);        // 合成时间戳        int startPoint = min * 60 * 1000                + sec * 1000                + msec * 10;        return startPoint;    }}

Lyric
public class Lyric implements Comparable<Lyric>{    private int startPoint;    private String content;    public Lyric(int startPoint, String content) {        this.startPoint = startPoint;        this.content = content;    }    public int getStartPoint() {        return startPoint;    }    public void setStartPoint(int startPoint) {        this.startPoint = startPoint;    }    public String getContent() {        return content;    }    public void setContent(String content) {        this.content = content;    }    @Override    public String toString() {        return "Lyric{" +                "startPoint=" + startPoint +                ", content='" + content + '\'' +                '}';    }    @Override    public int compareTo(Lyric another) {        return startPoint - another.startPoint;    }}




0 0
原创粉丝点击