zoukankan      html  css  js  c++  java
  • 自定义控件 TextView 歌词 Lrc


    演示

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    自定义View
    /**
     * 歌词播放的自定义控件
     */
    public class LrcView extends TextView {
        private String filePath = "/a.lrc";//文件路径
        private List<Lyrc> lyrcList;//歌词内容
        private int current = 0;//当前行
        private int lineSpacing = 70; //行间距
        //当前正在播放的行
        private Paint currentPaint;
        private int currentColor = Color.BLUE;//颜色
        private int currentSize = 55;//字体大小
        private Typeface currentTypeface = Typeface.DEFAULT_BOLD;//字体,默认的字体+粗体
        //其他行
        private Paint ortherPaint;
        private int ortherColor = Color.GREEN;
        private int ortherSize = 45;
        private Typeface ortherTypeface = Typeface.SERIF;//一种字体类型
        private Handler handler = new Handler() {
            public void handleMessage(Message msg) {
                invalidate();
            }
        };

        public LrcView(Context context) {
            this(context, null);
        }
        public LrcView(Context context, AttributeSet attrs) {
            super(context, attrs);
            lyrcList = LyrcUtil.readLRC(new File(Environment.getExternalStorageDirectory().getPath() + filePath));
            currentPaint = new Paint();
            currentPaint.setColor(currentColor);
            currentPaint.setTextSize(currentSize);
            currentPaint.setTextAlign(Align.CENTER);
            currentPaint.setTypeface(currentTypeface);
            ortherPaint = new Paint();
            ortherPaint.setColor(ortherColor);
            ortherPaint.setTextSize(ortherSize);
            ortherPaint.setTextAlign(Align.CENTER);
            ortherPaint.setTypeface(ortherTypeface);
        }

        public void setLrcType(String filePath, int lineSpacing, int currentColor, int currentSize, int ortherColor, int ortherSize) {
            lyrcList = LyrcUtil.readLRC(new File(filePath));
            this.lineSpacing = lineSpacing;
            
            currentPaint.setColor(currentColor);
            currentPaint.setTextSize(currentSize);
            ortherPaint.setColor(ortherColor);
            ortherPaint.setTextSize(ortherSize);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            if (current < lyrcList.size()) {
                if (lyrcList != null && lyrcList.size() > 0) {
                    Lyrc lyrc = null;
                    //画前面的内容
                    for (int i = current - 1; i >= 0; i--) {
                        lyrc = lyrcList.get(i);
                        canvas.drawText(lyrc.lrcString, getWidth() / 2, getHeight() / 2 + lineSpacing * (i - current), ortherPaint);
                    }
                    //画当前的内容
                    lyrc = lyrcList.get(current);
                    canvas.drawText(lyrc.lrcString, getWidth() / 2, getHeight() / 2, currentPaint);
                    //画后面的内容
                    for (int i = current + 1; i < lyrcList.size(); i++) {
                        lyrc = lyrcList.get(i);
                        canvas.drawText(lyrc.lrcString, getWidth() / 2, getHeight() / 2 + lineSpacing * (i - current), ortherPaint);
                    }
                    //告诉handler当前行的时间
                    lyrc = lyrcList.get(current);
                    handler.sendEmptyMessageDelayed(10, lyrc.sleepTime);
                    //当前行+1
                    current++;
                } else canvas.drawText("未找到歌词", getWidth() / 2, getHeight() / 2, currentPaint);
            }
            super.onDraw(canvas);
        }
    }

    工具类
    public class LyrcUtil {
        private static List<Lyrc> lyrcList;
        /**
         * 读取文件
         */
        public static List<Lyrc> readLRC(File f) {
            try {
                if (f == null || !f.exists()) {
                    lyrcList = null;
                } else {
                    lyrcList = new Vector<Lyrc>();
                    InputStream is = new BufferedInputStream(new FileInputStream(f));
                    BufferedReader br = new BufferedReader(new InputStreamReader(is, getCharset(f)));
                    String strTemp = "";
                    while ((strTemp = br.readLine()) != null) {
                        strTemp = analyzeLRC(strTemp);
                    }
                    br.close();
                    is.close();
                    // 对歌词进行排序
                    Collections.sort(lyrcListnew Sort());
                    // 计算每行歌词的停留时间
                    for (int i = 0; i < lyrcList.size(); i++) {
                        Lyrc one = lyrcList.get(i);
                        if (i + 1 < lyrcList.size()) {
                            Lyrc two = lyrcList.get(i + 1);
                            one.sleepTime = two.timePoint - one.timePoint;
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return lyrcList;
        }
        /**
         * 处理一行内容
         */
        private static String analyzeLRC(String text) {
            try {
                int pos1 = text.indexOf("[");
                int pos2 = text.indexOf("]");
                if (pos1 >= 0 && pos2 != -1) {
                    Long time[] = new Long[getPossiblyTagCount(text)];
                    time[0] = timeToLong(text.substring(pos1 + 1, pos2));
                    if (time[0] == -1) return "";
                    String strLineRemaining = text;
                    int i = 1;
                    while (pos1 >= 0 && pos2 != -1) {
                        strLineRemaining = strLineRemaining.substring(pos2 + 1);
                        pos1 = strLineRemaining.indexOf("[");
                        pos2 = strLineRemaining.indexOf("]");
                        if (pos2 != -1) {
                            time[i] = timeToLong(strLineRemaining.substring(pos1 + 1, pos2));
                            if (time[i] == -1) return ""// LRCText
                            i++;
                        }
                    }
                    Lyrc tl = null;
                    for (int j = 0; j < time.length; j++) {
                        if (time[j] != null) {
                            tl = new Lyrc();
                            tl.timePoint = time[j].intValue();
                            tl.lrcString = strLineRemaining;
                            lyrcList.add(tl);
                        }
                    }
                    return strLineRemaining;
                } else return "";
            } catch (Exception e) {
                return "";
            }
        }
        private static int getPossiblyTagCount(String Line) {
            String strCount1[] = Line.split("\[");
            String strCount2[] = Line.split("\]");
            if (strCount1.length == 0 && strCount2.length == 0) return 1;
            else if (strCount1.length > strCount2.lengthreturn strCount1.length;
            else return strCount2.length;
        }
        /**
         * 时间转换
         */
        public static long timeToLong(String Time) {
            try {
                String[] s1 = Time.split(":");
                int min = Integer.parseInt(s1[0]);
                String[] s2 = s1[1].split("\.");
                int sec = Integer.parseInt(s2[0]);
                int mill = 0;
                if (s2.length > 1) mill = Integer.parseInt(s2[1]);
                return min * 60 * 1000 + sec * 1000 + mill * 10;
            } catch (Exception e) {
                return -1;
            }
        }
        /**
         * 判断文件编码
         */
        public static String getCharset(File file) {
            String charset = "GBK";
            byte[] first3Bytes = new byte[3];
            try {
                boolean checked = false;
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                bis.mark(0);
                int read = bis.read(first3Bytes, 0, 3);
                if (read == -1) return charset;
                if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) {
                    charset = "UTF-16LE";
                    checked = true;
                } else if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) {
                    charset = "UTF-16BE";
                    checked = true;
                } else if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB && first3Bytes[2] == (byte) 0xBF) {
                    charset = "UTF-8";
                    checked = true;
                }
                bis.reset();
                if (!checked) {
                    int loc = 0;
                    while ((read = bis.read()) != -1) {
                        loc++;
                        if (read >= 0xF0) break;
                        if (0x80 <= read && read <= 0xBF) break;
                        if (0xC0 <= read && read <= 0xDF) {
                            read = bis.read();
                            if (0x80 <= read && read <= 0xBF) continue;
                            else break;
                        } else if (0xE0 <= read && read <= 0xEF) {
                            read = bis.read();
                            if (0x80 <= read && read <= 0xBF) {
                                read = bis.read();
                                if (0x80 <= read && read <= 0xBF) {
                                    charset = "UTF-8";
                                    break;
                                } else break;
                            } else break;
                        }
                    }
                }
                bis.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return charset;
        }
        private static class Sort implements Comparator<Lyrc> {
            public Sort() {
            }
            public int compare(Lyrc tl1, Lyrc tl2) {
                return sortUp(tl1, tl2);
            }
            private int sortUp(Lyrc tl1, Lyrc tl2) {
                if (tl1.timePoint < tl2.timePointreturn -1;
                else if (tl1.timePoint > tl2.timePointreturn 1;
                else return 0;
            }
        }
    }

    bean
    public class Lyrc {
        public String lrcString;
        public int sleepTime;
        public int timePoint;
    }

    a.lrc
    [00:00] 护花使者 [00:03] 李克勤 [00:38][00:05] 这晚在街中偶遇心中的她 [00:41][00:09] 两脚决定不听叫唤跟她归家 [00:44][00:12] 深宵的冷风 不准吹去她 [00:47][00:15] 她那幽幽眼神快要对我说话 [00:50][00:18] 纤纤身影飘飘身影默默转来吧 [00:54][00:21] 对我说浪漫情人爱我吗 [00:57][00:24] 贪心的晚风 竟敢拥吻她 [01:00][00:27] 将她秀发温温柔柔每缕每缕放下 [01:03][00:30] 卑污的晚风 不应抚慰她 [01:06][00:33] 我已决意一生护着心中的她

    使用
    public class MainActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            LrcView lrcView = new LrcView(this);
            lrcView.setLrcType(Environment.getExternalStorageDirectory().getPath() +"/a.lrc", dp2px(25), 0xffff00ff, dp2px(20), 0xff0000ff, dp2px(16));
            setContentView(lrcView);
        }
        /** 
            * 根据手机的分辨率从 dp 的单位 转成为 px(像素) 
            */
        public int dp2px(float dpValue) {
            float scale = getResources().getDisplayMetrics().density;
            return (int) (dpValue * scale + 0.5f);
        }
    }





  • 相关阅读:
    你做的页面有哪些浏览器测试过?这些浏览器的内核分别是什么?
    响应式布局
    Promise(二)
    Promise(一)
    同步和异步的自我理解
    null 与 undefined 区别
    python pandas 数据处理
    【python】list、tuple、dict、set、dataframe、narray、series之间的区别
    时间序列常用模型
    Linux系统学习笔记
  • 原文地址:https://www.cnblogs.com/baiqiantao/p/5439890.html
Copyright © 2011-2022 走看看