我们需要读取以上歌词文件的每一行转换成成一个个歌词实体:

代码如下:

public class LyricObject {

public int begintime; // 开始时间

public int endtime; // 结束时间

public int timeline; // 单句歌词用时

public String lrc; // 单句歌词

}

可根据当前播放器的播放进度与每句歌词的开始时间,得到当前屏幕中央高亮显示的那句歌词。在UI线程中另起线程,通过回调函数 onDraw() 每隔100ms重新绘制屏幕,实现歌词平滑滚动的动画效果。MainActivity代码如下:

代码如下:

import java.io.IOException;

import android.app.Activity;

import android.media.MediaPlayer;

import android.net.Uri;

import android.os.Bundle;

import android.os.Environment;

import android.os.Handler;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.SeekBar;

import android.widget.SeekBar.OnSeekBarChangeListener;

public class MainActivity extends Activity {

/** Called when the activity is first created. */

private LyricView lyricView;

private MediaPlayer mediaPlayer;

private Button button;

private SeekBar seekBar;

private String mp3Path;

private int INTERVAL=45;//歌词每行的间隔

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// this.requestWindowFeature(Window.FEATURE_NO_TITLE);

// getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

setContentView(R.layout.main);

mp3Path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/LyricSync/1.mp3";

lyricView = (LyricView) findViewById(R.id.mylrc);

mediaPlayer = new MediaPlayer();

// this.requestWindowFeature(Window.FEATURE_NO_TITLE);

ResetMusic(mp3Path);

SerchLrc();

lyricView.SetTextSize();

button = (Button) findViewById(R.id.button);

button.setText("播放");

seekBar = (SeekBar) findViewById(R.id.seekbarmusic);

seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

@Override

public void onStopTrackingTouch(SeekBar seekBar) {

// TODO Auto-generated method stub

}

@Override

public void onStartTrackingTouch(SeekBar seekBar) {

// TODO Auto-generated method stub

}

@Override

public void onProgressChanged(SeekBar seekBar, int progress,

boolean fromUser) {

// TODO Auto-generated method stub

if (fromUser) {

mediaPlayer.seekTo(progress);

lyricView.setOffsetY(220 - lyricView.SelectIndex(progress)

* (lyricView.getSIZEWORD() + INTERVAL-1));

}

}

});

button.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

if (mediaPlayer.isPlaying()) {

button.setText("播放");

mediaPlayer.pause();

} else {

button.setText("暂停");

mediaPlayer.start();

lyricView.setOffsetY(220 - lyricView.SelectIndex(mediaPlayer.getCurrentPosition())

* (lyricView.getSIZEWORD() + INTERVAL-1));

}

}

});

mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

@Override

public void onCompletion(MediaPlayer mp) {

ResetMusic(mp3Path);

lyricView.SetTextSize();

lyricView.setOffsetY(200);

mediaPlayer.start();

}

});

seekBar.setMax(mediaPlayer.getDuration());

new Thread(new runable()).start();

}

public void SerchLrc() {

String lrc = mp3Path;

lrc = lrc.substring(0, lrc.length() - 4).trim() + ".lrc".trim();

LyricView.read(lrc);

lyricView.SetTextSize();

lyricView.setOffsetY(350);

}

public void ResetMusic(String path) {

mediaPlayer.reset();

try {

mediaPlayer.setDataSource(mp3Path);

mediaPlayer.prepare();

} catch (IllegalArgumentException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalStateException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

class runable implements Runnable {

@Override

public void run() {

// TODO Auto-generated method stub

while (true) {

try {

Thread.sleep(100);

if (mediaPlayer.isPlaying()) {

lyricView.setOffsetY(lyricView.getOffsetY() - lyricView.SpeedLrc());

lyricView.SelectIndex(mediaPlayer.getCurrentPosition());

seekBar.setProgress(mediaPlayer.getCurrentPosition());

mHandler.post(mUpdateResults);

}

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

Handler mHandler = new Handler();

Runnable mUpdateResults = new Runnable() {

public void run() {

lyricView.invalidate(); // 更新视图

}

};

}

歌词View的代码如下:

代码如下:

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.Iterator;

import java.util.TreeMap;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.util.AttributeSet;

import android.util.Log;

import android.view.MotionEvent;

import android.view.View;

public class LyricView extends View{

private static TreeMap lrc_map;

private float mX; //屏幕X轴的中点,此值固定,保持歌词在X中间显示

private float offsetY; //歌词在Y轴上的偏移量,此值会根据歌词的滚动变小

private static boolean blLrc=false;

private float touchY; //当触摸歌词View时,保存为当前触点的Y轴坐标

private float touchX;

private boolean blScrollView=false;

private int lrcIndex=0; //保存歌词TreeMap的下标

private int SIZEWORD=0;//显示歌词文字的大小值

private int INTERVAL=45;//歌词每行的间隔

Paint paint=new Paint();//画笔,用于画不是高亮的歌词

Paint paintHL=new Paint(); //画笔,用于画高亮的歌词,即当前唱到这句歌词

public LyricView(Context context){

super(context);

init();

}

public LyricView(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

/* (non-Javadoc)

* @see android.view.View#onDraw(android.graphics.Canvas)

*/

@Override

protected void onDraw(Canvas canvas) {

if(blLrc){

paintHL.setTextSize(SIZEWORD);

paint.setTextSize(SIZEWORD);

LyricObject temp=lrc_map.get(lrcIndex);

canvas.drawText(temp.lrc, mX, offsetY+(SIZEWORD+INTERVAL)*lrcIndex, paintHL);

// 画当前歌词之前的歌词

for(int i=lrcIndex-1;i>=0;i--){

temp=lrc_map.get(i);

if(offsetY+(SIZEWORD+INTERVAL)*i

android 歌词解析 依赖,Android实现歌曲播放时歌词同步显示具体思路相关推荐

  1. Android 实现歌曲播放时歌词同步显示

    我们需要读取以上歌词文件的每一行转换成成一个个歌词实体: public class LyricObject { public int begintime; // 开始时间 public int end ...

  2. LRC歌词解析,实现Linux设备播放音乐显示歌词 LRC解析

    开始正文~~~ 1.关于LRC lrc是英文lyric(歌词)的缩写,被用做歌词文件的扩展名.以lrc为扩展名的歌词文件可以在各类数码播放器中同步显示.LRC 歌词是一种包含着"*:*&qu ...

  3. android 歌词解析时间,Android歌词秀设计思路(1)SafetyTimer

    Android中使用Timer时需要同时访问TimerTask,Handle等类,手续繁杂而且是真正想做的事淹没在手续化的代码中.本文介绍了的SafetyTimer类隐藏了TimerTask,Hand ...

  4. android studio管理依赖,Android Studio 中的 Gradle 依赖统一管理

    在我们的实际项目开发中,通常在一个 Project 项目中会存在多个 Module 的情况,在这些 Module 中会存在一些相同的版本依赖配置,针对进行版本升级的时候需要逐个修改,显得特别麻烦,所以 ...

  5. HTML随音乐播放时间自动歌词,JavaScript实时监听歌曲播放进度显示对应歌词

    前言 在之前我就想试试在线的音乐播放器的制作,昨晚动手实现了播放音乐的歌词实时对应显示的组件,下面就来看看其中的解析原理. 正文 这里我以李玉刚的<刚好遇见你>为例,首先我们需要获取到音频 ...

  6. android天气json数据,android JSON解析数据 android解析天气预报

    概要 笔者近期做到对天气预报JSON数据解析,在此小记. 天气预报接口:http://wthrcdn.etouch.cn/weather_mini?citykey=101200101 JSON数据如下 ...

  7. android全屏与非全屏切换时Toolbar的显示,仿微信漂流瓶效果

    Toolbar已经代替了actionbar,特别是在4.4或更高版本上可以有沉浸式效果,要使用Toolbar还要配置相关的Noactionbar style样式,但是如果在全屏与非全屏切换时,如何使用 ...

  8. android xml解析demo,Android解析自定义xml文件--Sax解析xml文件,测试demo(方案二)...

    转载请注明出处:http://blog.csdn.net/droyon/article/details/9346657 Sax解析xml 以下是测试Demo 运行程序类 public class Te ...

  9. android xpath解析xml,Android 中处理 XML 的四种方式-DOM

    Android 中处理 XML 的几种方式连载中,我们就不介绍合成 XML 了,因为合成 XML 可以直接拼接字符串,虽然看起很不高大上,但却很有效.我们主要介绍如何取 XML 中的值. 适用 DOM ...

最新文章

  1. sql server 备份计划
  2. 【CH - 1401】 兔子与兔子(字符串哈希)
  3. 如何“神还原”数据中心? 阿里联合NTU打造了工业级精度的仿真沙盘!
  4. Oracle(三):视图、序列、同义词、索引
  5. 实战系列-分布式缓存
  6. python 云计算开发是什么_云计算是什么?云计算开发学习路线
  7. 阶段5 3.微服务项目【学成在线】_day01 搭建环境 CMS服务端开发_13-MongoDb入门-数据库和集合...
  8. 代码整洁 vs 代码肮脏
  9. word文字铺满页面_word文字怎么铺满
  10. Adobe Premiere基础-介绍,配置,快捷键,创建项目,创建序列(一)
  11. 交叉熵、KL散度、Jeffery分歧、JS散度
  12. linux设备如何获取经纬度,openlayers鼠标移动获取地图经纬度格式化的两种方式
  13. 排序算法之归并排序 ( C语言版 )
  14. Flutter开发之Http网络请求
  15. dd 0x7ffe0000_当您尝试启动网站时出现“意外的错误0x8ffe2740”错误信息
  16. 学习Python爬虫东方财富网
  17. Latex并列摆放两张表格
  18. 企业软文营销如何断时间生效满足即时时代
  19. 展讯充电管理模块浅析(一)
  20. Homebrew关闭自动更新

热门文章

  1. java mdb文件_java读取mdb文件
  2. 【原创】取消交换机显示信息时的“more“
  3. 基于javaweb的在线游戏商城系统(java+springboot+mybatis+mysql+layui+jsp)
  4. 模具、金属加工制造行业MES解决方案
  5. POJ 2763 Housewife Wind 笔记
  6. 网络中的各层与http、https等协议
  7. 通达信 移动平均算法_通达信线性回归通道主图指标公式;通达信顶底轻松买卖副图指标公式...
  8. 第二次尝试制作html5游戏
  9. Django-MTV模型
  10. kisso是什么牌子_marie elie是什么牌子?marie elie品牌介绍