歌词 Lrc 自定义TextView

演示



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

    <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(lyrcList, new 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.length) return 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.timePoint) return -1;

            else if (tl1.timePoint > tl2.timePoint) return 1;

            else return 0;

        }

    }

}

使用


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);

    }

}

来自为知笔记(Wiz)

时间: 2024-10-18 17:21:16

歌词 Lrc 自定义TextView的相关文章

自定义TextView实现微信动态的全文和收起功能

本示例实现微信朋友圈发布动态后呈现的全文和收起功能. 1,自定义TextView的布局文件——my_text_view.xml 1 <?xml version="1.0" encoding="utf-8"?> 2 <!-- 自定义TextView,实现自动的添加全文和收起功能 --> 3 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/androi

自定义TextView 调用ttf格式字体

自定义TextView 调用ttf格式字体 <strong>将ttf格式文件存放在assets/fonts/下</strong> 注:PC系统字体存放在C:\Windows\Fonts下 import android.content.Context; import android.graphics.Typeface; import android.util.AttributeSet; import android.widget.TextView; /** * 修改字体 * */ p

Android 自定义TextView实现文本内容自动调整字体大小以适应TextView的大小

最近做通讯录小屏机 联系人姓名显示--长度超过边界字体变小 /**   * 自定义TextView,文本内容自动调整字体大小以适应TextView的大小   * @author yzp   */   public class AutoFitTextView extends TextView {       private Paint mTextPaint;       private float mTextSize;          public AutoFitTextView(Context

自定义TextView使之具有跑马灯的效果

一.问题的引入 使用普通的textview跑马的效果,一开始没有焦点事件不会进行滚动,button有焦点事件,但是比较难看,因此需要自定一个TextView 一出生就有焦点 然后需要自定义一个textview FocusedTextView.java package com.xuliugen.mobilesafe.ui; import android.content.Context; import android.util.AttributeSet; import android.view.Vi

Android开发学习笔记-自定义TextView属性模版

如果项目中有很多个控件使用的是同一种样式,则为了方便,可以将样式设置到系统中去,这样使用的时候会方便很多. 下面是自定义样式模版的方法. 1.在style.xml文件中添加自己要设置的样式内容 <resources> <!-- Base application theme, dependent on API level. This theme is replaced by AppBaseTheme from res/values-vXX/styles.xml on newer devic

练习,自定义TextView(1.1)

重新自定义TextView是非常有趣的事情,跟着Android4高级编程,通过自定义TextView,来敲一下代码: 这个是那么的简单,自定义TextView,新建CustomTextView继承TextView public class CustomTextView extends TextView { private Paint marginPaint; private Paint linePaint; private int paperColor; private float margin

自定义textView限制字数

ViewController.m #import "JYZTextView.h" #define kTextBorderColor     RGBCOLOR(227,224,216)   #undef  RGBCOLOR #define RGBCOLOR(r,g,b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1] @interface ViewController ()<UITextViewDe

自定义TextView带有各类.ttf字体的TextView

最近项目遇到了将普通文字转化为带有字体样式的文字,这里就涉及到了.ttf文件,我上网百度了不少资料最终终于实现了,现在想想其实并不复杂 1,你需要下载一种.ttf字体文件,你可以从网上找到一种字体的.ttf 文件,放在assets中,比如取名为ll.ttf 2.下面我们可以自定义TextView了,比较简单,设置一下我们导入的.ttf文件即可 1 public class FontsTextView extends android.support.v7.widget.AppCompatTextV

Android之——自定义TextView

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47082241 在这一篇博文中,将向大家介绍如何以最简单的方式,来自定义Android中的控件,下面我们以自定义TextView为例来向大家介绍如何自定义Android中的控件. 首先,我们来简单说一下Android中自定义控件的原理:创建一个类,继承要自定义的控件类,重写父类的相关方法即可.原理说完了,是不是很简单呢?下面,我们就一起来自定义一个TextView控件吧. 1.创建