频道栏目
首页 > 程序开发 > 移动开发 > Android > 正文
Android自定义控件——歌词显示
2017-03-24 09:15:49         来源:qq_27856623的博客  
收藏   我要投稿

Android自定义控件——歌词显示。这段时间在写一个音乐播放器,需要显示歌词,下面是我写的一个歌词显示的view。目前它已经可以完成歌词的基本显示,细节地方后期继续完善。

MainActivity从资源文件读入歌词,歌曲,并利用正则表达式解析歌词变为我们想要的格式。解析之后得到两个list: timeList 和 contentList。我们把这两个list传入LrcView中,然后显示。

歌词是下载百度音乐的歌词解析的,我觉得自己写的很麻烦。如果大家有更好的方法可以留言告诉我。下面是歌词的原本格式。

歌词原本格式

解析之后的格式:

解析之后

下面是代码部分

1:MainActivity

import android.media.MediaPlayer;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.util.Log;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.List;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

public class MainActivity extends AppCompatActivity {

MediaPlayer mediaPlayer = new MediaPlayer();

private LrcView lrcView = null;

private List timeList = new ArrayList<>();

private List contentList = new ArrayList<>();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

InputStream inputStream =getResources().openRawResource(R.raw.apologize);//从资源文件里面得到输入流

AnalyseLyricFile(inputStream);

Log.e("size",""+timeList.size());

mediaPlayer = MediaPlayer.create(this, R.raw.appolo);

lrcView = (LrcView) super.findViewById(R.id.lyric_show);

lrcView.setList(timeList,contentList);

lrcView.init();

new Thread(lrcView).start();

mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

@Override

public void onCompletion(MediaPlayer mp) {

mediaPlayer.release();//歌曲播放完释放mediaplayer

}

});

mediaPlayer.start();//开始播放

}

public void AnalyseLyricFile(InputStream inputStream){ //参数是歌词文件的路径

BufferedReader reader = null;

InputStreamReader inputFileReader = null;

String tempString = null;

//正则表达式解析出时间戳

Pattern timePattern = Pattern.compile("(.*?)]");

String time = "";

long timestamp = 0;

long timePadding = 0;//帮助得到每行歌词显示时间的变量

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");//把字符串转换为时间

try {

inputFileReader = new InputStreamReader(inputStream, "utf-8");

reader = new BufferedReader(inputFileReader);

// 一次读入一行,直到读入null为文件结束

while ((tempString = reader.readLine()) != null) {

Matcher timeMatcher = timePattern.matcher(tempString);

if (timeMatcher.find()){//如果匹配到符合结果

time = timeMatcher.group(1);//不要后面的中括号

if((int)time.charAt(1) <= 57){//非数字选项,目前没有分析音乐的标题,作曲家

time = time.replace('.', ':');

time = time.substring(1, time.length());

String temp [] = time.split(":");

try {

timestamp = simpleDateFormat.parse("1970010108"+temp[0]+temp[1]).getTime();//电脑的开始计时时间是从1970年1月1日早上8点钟开始

timestamp+=10*Integer.parseInt(temp[2]);

timeList.add(timestamp-timePadding);

contentList.add(" "+tempString.substring(10, tempString.length()));

timePadding = timestamp;

} catch (ParseException e) {

e.printStackTrace();

}

}

}

}

reader.close();

} catch (IOException e) {

e.printStackTrace();

} finally {

if (reader != null) {

try {

reader.close();

} catch (IOException e1) {

}

}

}

}

}

这是具体显示的代码

2:LrcView代码

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.util.DisplayMetrics;

import android.util.Log;

import android.view.View;

import java.util.ArrayDeque;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

import java.util.Queue;

public class LrcView extends View implements Runnable{

private int width = 1080;//xml中设定的歌词宽度

private int heght = 1000;//xml中设定的歌词高度

private Paint paint1 = null;//用于绘画当前正在播放的歌词

private Paint paint2 = null;//用于绘画非当前播放的歌词

private int padding = 100;//歌词的行间距

private int textSize = 18;

private int index = 1;//正在播放歌词段所在下标

private int lines = 1;//总共要显示多少行歌词

private int count = 0;//记录应该取哪一列歌词

private boolean hasLyric = true;

private List timeList = new ArrayList<>();

private List contentList = new ArrayList<>();

private Queue queue = new ArrayDeque();//用于储存当前正在展示的歌词,只显示十行的内容

/**

* 歌词显示时间相关的参数

*/

private long timePastBy = 0;//歌词已经显示的时间

public LrcView(Context context, AttributeSet attributeSet){

super(context,attributeSet);

}

public void init(){//初始化歌词是通过给这个view一个 String list

count = 0;

if(contentList.size()== 0){//没有歌词

contentList.add("Just enjoy!");

}

setFocusable(true);

lines = heght/padding;//得到可以显示多少行歌词

index = lines/2;//正在播放歌词的所在下标

for(int i = 0;i0) {

timePastBy+=timeList.get(0);//歌词已经显示了多久,为调整歌词进度设定(目前还没有添加这个功能)

Thread.sleep(timeList.remove(0));//每行歌词显示的时间

move();

}

}catch (Exception e){

e.printStackTrace();

}

}

}

public void setList(List l1,List l2){

timeList = l1;

contentList = l2;

}

}

3:activity_main

这是最终效果图:

效果图
点击复制链接 与好友分享!回本站首页
上一篇:Android 适配不同屏幕(手机,平板)
下一篇:Android viewpager + fragment实现fragment之间的切换
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站