用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字
云代码 - android代码库

Android应用开发--MP3音乐播放器滚动歌词实现

2015-01-23 作者: Jen举报

[android]代码库

201362日  简、美音乐播放器开发记录
-----主题
     这篇博客的主题是:“滚动歌词的实现”
     要的效果如下:
              
----实现过程
1. 建立歌词内容实体类
2. 自定义View
3. 加入布局文件
4. 编写歌词处理类
5. 在Service里面实现同步更新歌词
 
----代码实现
--LrcContent.java
package com.wwj.sb.domain;
/**
 * 2013/6/1
 * @author wwj
 * 歌词实体类
 */
public class LrcContent {
    private String lrcStr;  //歌词内容
    private int lrcTime;    //歌词当前时间
    public String getLrcStr() {
        return lrcStr;
    }
    public void setLrcStr(String lrcStr) {
        this.lrcStr = lrcStr;
    }
    public int getLrcTime() {
        return lrcTime;
    }
    public void setLrcTime(int lrcTime) {
        this.lrcTime = lrcTime;
    }
}
--LrcView.java
package com.wwj.sb.custom;
 
import java.util.ArrayList;
import java.util.List;
 
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 com.wwj.sb.domain.LrcContent;
 
/**
 * 自定义绘画歌词,产生滚动效果
 * @author wwj
 *
 */
public class LrcView extends android.widget.TextView {
    private float width;        //歌词视图宽度
    private float height;       //歌词视图高度
    private Paint currentPaint; //当前画笔对象
    private Paint notCurrentPaint;  //非当前画笔对象
    private float textHeight = 25//文本高度
    private float textSize = 18;        //文本大小
    private int index = 0;      //list集合下标
     
     
    private List<LrcContent> mLrcList = new ArrayList<LrcContent>();
     
    public void setmLrcList(List<LrcContent> mLrcList) {
        this.mLrcList = mLrcList;
    }
 
    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(24);
        currentPaint.setTypeface(Typeface.SERIF);
         
        notCurrentPaint.setTextSize(textSize);
        notCurrentPaint.setTypeface(Typeface.DEFAULT);
         
        try {
            setText("");
            canvas.drawText(mLrcList.get(index).getLrcStr(), width / 2, height / 2, currentPaint);
             
            float tempY = height / 2;
            //画出本句之前的句子
            for(int i = index - 1; i >= 0; i--) {
                //向上推移
                tempY = tempY - textHeight;
                canvas.drawText(mLrcList.get(i).getLrcStr(), width / 2, tempY, notCurrentPaint);
            }
            tempY = height / 2;
            //画出本句之后的句子
            for(int i = index + 1; i < mLrcList.size(); i++) {
                //往下推移
                tempY = tempY + textHeight;
                canvas.drawText(mLrcList.get(i).getLrcStr(), width / 2, tempY, notCurrentPaint);
            }
        } catch (Exception e) {
            setText("...木有歌词文件,赶紧去下载...");
        }
    }
 
    /**
     * 当view大小改变的时候调用的方法
     */
    @Override
    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;
    }
     
}
--LrcProcess.java
package com.wwj.sb.custom;
 
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
 
import android.util.Xml.Encoding;
import android.widget.SlidingDrawer;
 
import com.wwj.sb.domain.LrcContent;
 
/**
 * 2013/6/1
 * @author  wwj
 *  处理歌词的类
 */
public class LrcProcess {
    private List<LrcContent> lrcList; //List集合存放歌词内容对象
    private LrcContent mLrcContent;     //声明一个歌词内容对象
    /**
     * 无参构造函数用来实例化对象
     */
    public LrcProcess() {
        mLrcContent = new LrcContent();
        lrcList = new ArrayList<LrcContent>();
    }
     
    /**
     * 读取歌词
     * @param path
     * @return
     */
    public String readLRC(String path) {
        //定义一个StringBuilder对象,用来存放歌词内容
        StringBuilder stringBuilder = new StringBuilder();
        File f = new File(path.replace(".mp3", ".lrc"));
         
        try {
            //创建一个文件输入流对象
            FileInputStream fis = new FileInputStream(f);
            InputStreamReader isr = new InputStreamReader(fis, "utf-8");
            BufferedReader br = new BufferedReader(isr);
            String s = "";
            while((s = br.readLine()) != null) {
                //替换字符
                s = s.replace("[", "");
                s = s.replace("]", "@");
                 
                //分离“@”字符
                String splitLrcData[] = s.split("@");
                if(splitLrcData.length > 1) {
                    mLrcContent.setLrcStr(splitLrcData[1]);
                     
                    //处理歌词取得歌曲的时间
                    int lrcTime = time2Str(splitLrcData[0]);
                     
                    mLrcContent.setLrcTime(lrcTime);
                     
                    //添加进列表数组
                    lrcList.add(mLrcContent);
                     
                    //新创建歌词内容对象
                    mLrcContent = new LrcContent();
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            stringBuilder.append("木有歌词文件,赶紧去下载!...");
        } catch (IOException e) {
            e.printStackTrace();
            stringBuilder.append("木有读取到歌词哦!");
        }
        return stringBuilder.toString();
    }
    /**
     * 解析歌词时间
     * 歌词内容格式如下:
     * [00:02.32]陈奕迅
     * [00:03.43]好久不见
     * [00:05.22]歌词制作  王涛
     * @param timeStr
     * @return
     */
    public int time2Str(String timeStr) {
        timeStr = timeStr.replace(":", ".");
        timeStr = timeStr.replace(".", "@");
         
        String timeData[] = timeStr.split("@"); //将时间分隔成字符串数组
         
        //分离出分、秒并转换为整型
        int minute = Integer.parseInt(timeData[0]);
        int second = Integer.parseInt(timeData[1]);
        int millisecond = Integer.parseInt(timeData[2]);
         
        //计算上一行与下一行的时间转换为毫秒数
        int currentTime = (minute * 60 + second) * 1000 + millisecond * 10;
        return currentTime;
    }
    public List<LrcContent> getLrcList() {
        return lrcList;
    }
}
加入布局文件:
    <com.wwj.sb.custom.LrcView
        android:id="@+id/lrcShowView"
        android:layout_width="match_parent"
        android:layout_height="200dip"
        android:layout_above="@+id/footer_layout"
        android:layout_below="@+id/header_layout"
        android:layout_centerHorizontal="true" />
--在Service.java中的实现,这里就不贴完整的Service类了,主要是如何在Service实现歌词同步的。
声明变量:
private LrcProcess mLrcProcess; //歌词处理
private List<LrcContent> lrcList = new ArrayList<LrcContent>(); //存放歌词列表对象
private int index = 0;          //歌词检索值
核心实现代码:
    /**
     * 初始化歌词配置
     */
    public void initLrc(){
        mLrcProcess = new LrcProcess();
        //读取歌词文件
        mLrcProcess.readLRC(mp3Infos.get(current).getUrl());
        //传回处理后的歌词文件
        lrcList = mLrcProcess.getLrcList();
        PlayerActivity.lrcView.setmLrcList(lrcList);
        //切换带动画显示歌词
        PlayerActivity.lrcView.setAnimation(AnimationUtils.loadAnimation(PlayerService.this,R.anim.alpha_z));
        handler.post(mRunnable);
    }
    Runnable mRunnable = new Runnable() {
         
        @Override
        public void run() {
            PlayerActivity.lrcView.setIndex(lrcIndex());
            PlayerActivity.lrcView.invalidate();
            handler.postDelayed(mRunnable, 100);
        }
    };
    /**
     * 根据时间获取歌词显示的索引值
     * @return
     */
    public int lrcIndex() {
        if(mediaPlayer.isPlaying()) {
            currentTime = mediaPlayer.getCurrentPosition();
            duration = mediaPlayer.getDuration();
        }
        if(currentTime < duration) {
            for (int i = 0; i < lrcList.size(); i++) {
                if (i < lrcList.size() - 1) {
                    if (currentTime < lrcList.get(i).getLrcTime() && i == 0) {
                        index = i;
                    }
                    if (currentTime > lrcList.get(i).getLrcTime()
                            && currentTime < lrcList.get(i + 1).getLrcTime()) {
                        index = i;
                    }
                }
                if (i == lrcList.size() - 1
                        && currentTime > lrcList.get(i).getLrcTime()) {
                    index = i;
                }
            }
        }
        return index;
    }
其实,小巫还想实现可以拖动歌词来控制播放进度,还有自动搜索歌词等更加完备的实现。


网友评论    (发表评论)

共1 条评论 1/1页

发表评论:

评论须知:

  • 1、评论每次加2分,每天上限为30;
  • 2、请文明用语,共同创建干净的技术交流环境;
  • 3、若被发现提交非法信息,评论将会被删除,并且给予扣分处理,严重者给予封号处理;
  • 4、请勿发布广告信息或其他无关评论,否则将会删除评论并扣分,严重者给予封号处理。


扫码下载

加载中,请稍后...

输入口令后可复制整站源码

加载中,请稍后...