用户注册



邮箱:

密码:

用户登录


邮箱:

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

发表随想


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

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

2015-01-23 作者: Jen举报

[android]代码库

2013年6月2日  简、美音乐播放器开发记录
-----主题
     这篇博客的主题是:“滚动歌词的实现”
     要的效果如下:
             
----实现过程
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、请勿发布广告信息或其他无关评论,否则将会删除评论并扣分,严重者给予封号处理。


扫码下载

加载中,请稍后...

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

加载中,请稍后...