实现歌词滚动

## LrcView 自定义控件 ##

package com.example.music.lrc;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;

public class LrcView extends TextView {

private float width; // 歌词视图宽度
private float height; // 歌词视图高度
private Paint currentPaint; // 当前画笔对象
private Paint notCurrentPaint; // 非当前画笔对象
private float textHeight = 50; // 文本高度
private float textMaxSize = 24; //高亮文本大小
private float textSize = 20; // 文本大小
private int index = 0; // list集合下标
private LrcInfo infos; // 歌词信息

public void setmLrcList(LrcInfo infos) {
    this.infos = infos;
}

public LrcView(Context context) {
    super(context);
    init();
}

public LrcView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
}

public LrcView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

private void init() {

    setFocusable(true); // 设置可对焦
    // 显示歌词部分
    currentPaint = new Paint();
    currentPaint.setAntiAlias(true); // 设置抗锯齿,让文字美观饱满
    currentPaint.setTextAlign(Paint.Align.CENTER);// 设置文本对齐方式

    // 非高亮部分
    notCurrentPaint = new Paint();
    notCurrentPaint.setAntiAlias(true);
    notCurrentPaint.setTextAlign(Paint.Align.CENTER);
}

/**
 * 绘画歌词
 */
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (canvas == null) {
        return;
    }

    currentPaint.setColor(Color.argb(210, 251, 248, 29));
    notCurrentPaint.setColor(Color.argb(140, 255, 255, 255));

    currentPaint.setTextSize(textMaxSize);
    currentPaint.setTypeface(Typeface.SERIF);

    notCurrentPaint.setTextSize(textSize);
    notCurrentPaint.setTypeface(Typeface.DEFAULT);

    try {
        setText("");
        canvas.drawText(infos.getLrcLists().get(index).getContent(), width / 2, height / 2, currentPaint);
        float tempY = height / 2;
        // 画出本句之前的句子
        for (int i = index - 1; i >= 0; i--) {
            // 向上推移
            tempY = tempY - textHeight;
            canvas.drawText(infos.getLrcLists().get(i).getContent(), width / 2, tempY, notCurrentPaint);
        }
        tempY = height / 2;
        // 画出本句之后的句子
        for (int i = index + 1; i < infos.getLrcLists().size(); i++) {
            // 往下推移
            tempY = tempY + textHeight;
            canvas.drawText(infos.getLrcLists().get(i).getContent(), width / 2, tempY, notCurrentPaint);
        }
    } catch (Exception e) {
        setText("...缺少歌词文件...");
    }

}

/**
 * 当view大小改变的时候调用的方法
 */

protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    this.width = w;
    this.height = h;
}

public void setIndex(int index) {
    this.index = index;
}
}

LrcParse 类

package com.example.music.lrc;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LrcParse {

    private LrcInfo lrcInfo = new LrcInfo();
    public static String charSet = "utf-8"; //编码格式

    //歌词存放地地方
    private String Path;
    //时间
    private long currentTime;
    //对应时间的内容
    private String currentContent;

    //保存时间点和内容
    ArrayList lrcLists = new ArrayList();


    private InputStream inputStream;

    public LrcParse(String path) {

        this.Path = path.replace(".mp3", ".lrc");
    }

    public LrcInfo readLrc() {
        //定义一个StringBuilder对象,用来存放歌词内容
        StringBuilder stringBuilder = new StringBuilder();
        try {

            inputStream = new FileInputStream(this.Path);
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charSet));
            String str = null;
            //逐行解析
            while ((str = reader.readLine()) != null) {
                if (!str.equals("")) {
                    decodeLine(str);
                }
            }
            //全部解析完后,设置lrcLists
            lrcInfo.setLrcLists(lrcLists);
            return lrcInfo;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            LrcList lrcList = new LrcList();
            //设置时间点和内容的映射
            lrcList.setContent("歌词文件没发现!");
            lrcLists.add(lrcList);
            lrcInfo.setLrcLists(lrcLists);
            return lrcInfo;
        } catch (IOException e) {
            e.printStackTrace();
            LrcList lrcList = new LrcList();
            //设置时间点和内容的映射
            lrcList.setContent("没有读取到歌词!");
            lrcLists.add(lrcList);
            lrcInfo.setLrcLists(lrcLists);
            return lrcInfo;
        }

    }

    /**
     * 单行解析
     */
    private LrcInfo decodeLine(String str) {

        if (str.startsWith("[ti:")) {
            // 歌曲名
            lrcInfo.setTitle(str.substring(4, str.lastIndexOf("]")));
            //   lrcTable.put("ti", str.substring(4, str.lastIndexOf("]")));

        } else if (str.startsWith("[ar:")) {// 艺术家
            lrcInfo.setArtist(str.substring(4, str.lastIndexOf("]")));

        } else if (str.startsWith("[al:")) {// 专辑
            lrcInfo.setAlbum(str.substring(4, str.lastIndexOf("]")));

        } else if (str.startsWith("[by:")) {// 作词
            lrcInfo.setBySomeBody(str.substring(4, str.lastIndexOf("]")));

        } else if (str.startsWith("[la:")) {// 语言
            lrcInfo.setLanguage(str.substring(4, str.lastIndexOf("]")));
        } else {

            //设置正则表达式,可能出现一些特殊的情况
            String timeflag = "\\[(\\d{1,2}:\\d{1,2}\\.\\d{1,2})\\]|\\[(\\d{1,2}:\\d{1,2})\\]";

            Pattern pattern = Pattern.compile(timeflag);
            Matcher matcher = pattern.matcher(str);
            //如果存在匹配项则执行如下操作
            while (matcher.find()) {
                //得到匹配的内容
                String msg = matcher.group();
                //得到这个匹配项开始的索引
                int start = matcher.start();
                //得到这个匹配项结束的索引
                int end = matcher.end();
                //得到这个匹配项中的数组
                int groupCount = matcher.groupCount();
                for (int index = 0; index < groupCount; index++) {
                    String timeStr = matcher.group(index);
                    if (index == 0) {
                        //将第二组中的内容设置为当前的一个时间点
                        currentTime = str2Long(timeStr.substring(1, timeStr.length() - 1));
                    }
                }

                //得到时间点后的内容
                String[] content = pattern.split(str);

                //将内容设置为当前内容,需要判断只出现时间的情况,没有内容的情况
                if (content.length == 0) {
                    currentContent = "";
                } else {
                    currentContent = content[content.length - 1];
                }
                LrcList lrcList = new LrcList();
                //设置时间点和内容的映射
                lrcList.setCurrentTime(currentTime);
                lrcList.setContent(currentContent);
                lrcLists.add(lrcList);

            }

        }
        return this.lrcInfo;
    }

    private long str2Long(String timeStr) {
        //将时间格式为xx:xx.xx,返回的long要求以毫秒为单位
        String[] s = timeStr.split("\\:");
        int min = Integer.parseInt(s[0]);
        int sec = 0;
        int mill = 0;
        if (s[1].contains(".")) {
            String[] ss = s[1].split("\\.");
            sec = Integer.parseInt(ss[0]);
            mill = Integer.parseInt(ss[1]);
        } else {
            sec = Integer.parseInt(s[1]);
        }
        //时间的组成
        return min * 60 * 1000 + sec * 1000 + mill * 10;
    }
}
package com.example.music.lrc;

public class LrcList {
     //保存当前时间
    private long currentTime;
    //保存内容
    private String content;

    public long getCurrentTime() {
        return currentTime;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setCurrentTime(long currentTime) {
        this.currentTime = currentTime;
    }

    public String getContent() {
        return content;
    }
}
package com.example.music.lrc;

import java.util.ArrayList;

public class LrcInfo {

    private String title;//标题
    private String artist;//歌手
    private String album;//专辑名字
    private String bySomeBody;//歌词制作者
    private String offset;
    private String language;   //语言
    private String errorinfo;   //错误信息


    //保存歌词信息和时间点
    ArrayList lrcLists;

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public void setErrorinfo(String errorinfo) {
        this.errorinfo = errorinfo;
    }

    public String getErrorinfo() {
        return errorinfo;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public String getAlbum() {
        return album;
    }

    public void setAlbum(String album) {
        this.album = album;
    }

    public String getBySomeBody() {
        return bySomeBody;
    }

    public void setBySomeBody(String bySomeBody) {
        this.bySomeBody = bySomeBody;
    }

    public String getOffset() {
        return offset;
    }

    public void setOffset(String offset) {
        this.offset = offset;
    }

    public ArrayList getLrcLists() {
        return lrcLists;
    }

    public void setLrcLists(ArrayList lrcLists) {
        this.lrcLists = lrcLists;
    }
}

然后在到MusicService服务类里面调用

Handler handler = new Handler() {
    };
public void initLrc(String path) {

        LrcInfo mlrcInfo = new LrcInfo();
        //建立歌词对象
       LrcParse lrcParser = new LrcParse(path);
        //读歌词,并将数据传给歌词信息类
       mlrcInfo = lrcParser.readLrc();
        //获得歌词中的结点
        lrcLists = mlrcInfo.getLrcLists();
        //在MainActivity里面设置静态来共享数据
        MainActivity.lrcView.setmLrcList(mlrcInfo);
        //切换带动画显示歌词
        MainActivity.lrcView.setAnimation(AnimationUtils.loadAnimation(MusicService.this, R.anim.alpha_z));
        handler.post(mRunnable);
    }

    Runnable mRunnable = new Runnable() {

        @Override
        public void run() {
            MainActivity.lrcView.setIndex(lrcIndex());
            MainActivity.lrcView.invalidate();
            handler.postDelayed(mRunnable, 100);
        }
    };


    public int lrcIndex() {
        if (mediaPlayer.isPlaying()) {
            curplaytime2 = mediaPlayer.getCurrentPosition();
            duration2 = mediaPlayer.getDuration();
        }
        if (curplaytime2 < duration2) {
            for (int i = 0; i < lrcLists.size(); i++) {
                if (i < lrcLists.size() - 1) {
                    if (curplaytime2 < lrcLists.get(i).getCurrentTime() && i == 0) {
                        index = i;
                    }
                    if ((curplaytime2 > lrcLists.get(i).getCurrentTime())&& curplaytime2 < lrcLists.get(i+1).getCurrentTime()) {
                        index = i;
                    }
                }
                if ((i == lrcLists.size() - 1)&& curplaytime2 > lrcLists.get(i).getCurrentTime()) {
                    index = i;
                }
            }
        }
        return index;
    }

MainActivity就是主活动界面,在界面初始化自定义控件,当然也要在布局文件里面加上布局。R.anim.alpha_z 这个我也不知道是效果,所以不写了
歌词文件可以自己制作哦,在百度里面搜索lrc格式的歌词,然后自己新建一个文件夹,改一下后缀.lrc,当然文件名要跟歌曲名一样
摘抄自http://blog.csdn.net/wwj_748/article/details/9006567

你可能感兴趣的:(UI笔记)