当前位置:  编程技术>移动开发

Android实现歌曲播放时歌词同步显示具体思路

    来源: 互联网  发布时间:2014-10-17

    本文导语:  我们需要读取以上歌词文件的每一行转换成成一个个歌词实体: 代码如下: public class LyricObject { public int begintime; // 开始时间 public int endtime; // 结束时间 public int timeline; // 单句歌词用时 public String lrc; // 单句歌词 } 可根据当前...

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

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 再按一次返回键退出程序实现思路
  • Android TableLayout数据列表的回显清空实现思路及代码
  • android获取照片的快照 思路及实现方法
  • Android中设置只有程序第一次运行才显示的界面实现思路
  • android dialog边框去除白色边框实现思路及代码
  • android 类似微信的摇一摇功能实现思路及代码
  • android实现横屏的代码及思路
  • Android模拟器中窗口截图存成文件实现思路及代码
  • Android自定义格式显示Button的布局思路
  • android获取音乐文件的内置专辑图片实现思路及代码
  • Android 使用Intent传递数据的实现思路与代码
  • Android生存指南之:解Bug策略与思路问题的详解
  • Android中获取网页表单中的数据实现思路及代码
  • Android Metro菜单实现思路及代码
  • android 仿微信聊天气泡效果实现思路
  • Android自定义Adapter的ListView的思路及代码
  • Android列表实现(3)_自定义列表适配器思路及实现代码
  • android 自定义ScrollView实现背景图片伸缩的实现代码及思路
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • Android 按后退键退出Android程序的实现方法
  • android panellistview 圆角实现代码
  • Android实现弹出键盘的方法
  • Android实现信号强度监听的方法
  • Android设置桌面背景图片的实现方法
  • 请教如何在android平台下实现每个进程的流量监控?
  • Android平台的QT实现 Necessitas
  • Android实现关机重启的方法分享
  • android activity设置无标题实现全屏
  • android实现关闭或开启移动网络数据
  • android4.0屏蔽HOME键的简单实现
  • Android 实现永久保存数据的方法详解
  • Android手机获取root权限并实现关机重启功能的方法
  • android开发教程之实现toast工具类
  • Android判断屏幕是横屏或是竖屏的简单实现方法
  • Android中button实现onclicklistener事件的两种方式
  • Android实现动态显示或隐藏密码输入框的内容
  • Android实现Flip翻转动画效果
  • android实现背景平铺的三种方法
  • Android创建文件实现对文件监听示例
  • 申请Android Map 的API Key(v2)的最新申请方式(SHA1密钥)
  • Android瀑布流实例 android_waterfall
  • Android开发需要的几点注意事项总结
  • Android系统自带样式 (android:theme)
  • android 4.0 托管进程介绍及优先级和回收机制
  • Android网络共享软件 Android Wifi Tether
  • Android访问与手机通讯相关类的介绍
  • Android 图标库 Android GraphView
  • Android及andriod无线网络Wifi开发的几点注意事项
  • 轻量级Android开发工具 Android Tools
  • Android 2.3 下StrictMode介绍




  • 特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3