最近在做android 的MP3播放的项目,要实现歌词的自动滚动,以及同步显示。

lyric的歌词解析主要用yoyoplayer里面的,

显示部分参考了http://ishelf.iteye.com/blog/740402 ,这里只是模拟MP3歌词的滚动。

先上一下效果图:

滚动实现的代码其实也简单。显示画出当前时间点的歌词,然后再分别画出改歌词后面和前面的歌词,前面的部分往上推移,后面的部分往下推移,这样就保持了当前时间歌词在中间。

代码如下 LyricView,相关信息在注释了标明了。

view plain copy to clipboard print ?
  1. package  ru.org.piaozhiye.lyric;
  2. import  java.io.File;
  3. import  java.util.List;
  4. import  android.content.Context;
  5. import  android.graphics.Canvas;
  6. import  android.graphics.Color;
  7. import  android.graphics.Paint;
  8. import  android.graphics.Path;
  9. import  android.graphics.Typeface;
  10. import  android.util.AttributeSet;
  11. import  android.widget.TextView;
  12. /**
  13. * @author root
  14. *
  15. */
  16. public  class  LyricView extends  TextView {
  17. private  Paint mPaint;
  18. private  float  mX;
  19. private  static  Lyric mLyric;
  20. private  Paint mPathPaint;
  21. public  String test = "test" ;
  22. public  int  index = 0 ;
  23. private  List<Sentence> list;
  24. public  float  mTouchHistoryY;
  25. private  int  mY;
  26. private  long  currentDunringTime; // 当前行歌词持续的时间,用该时间来sleep
  27. private  float  middleY;// y轴中间
  28. private  static  final  int  DY = 50 ; // 每一行的间隔
  29. public  LyricView(Context context) {
  30. super (context);
  31. init();
  32. }
  33. public  LyricView(Context context, AttributeSet attr) {
  34. super (context, attr);
  35. init();
  36. }
  37. public  LyricView(Context context, AttributeSet attr, int  i) {
  38. super (context, attr, i);
  39. init();
  40. }
  41. private  void  init() {
  42. setFocusable(true );
  43. PlayListItem pli = new  PlayListItem("Because Of You" ,
  44. "/sdcard/MP3/Because Of You.mp3" , 0L, true );
  45. mLyric = new  Lyric(new  File("/sdcard/MP3/Because Of You.lrc" ), pli);
  46. list = mLyric.list;
  47. // 非高亮部分
  48. mPaint = new  Paint();
  49. mPaint.setAntiAlias(true );
  50. mPaint.setTextSize(22 );
  51. mPaint.setColor(Color.WHITE);
  52. mPaint.setTypeface(Typeface.SERIF);
  53. // 高亮部分 当前歌词
  54. mPathPaint = new  Paint();
  55. mPathPaint.setAntiAlias(true );
  56. mPathPaint.setColor(Color.RED);
  57. mPathPaint.setTextSize(22 );
  58. mPathPaint.setTypeface(Typeface.SANS_SERIF);
  59. }
  60. protected  void  onDraw(Canvas canvas) {
  61. super .onDraw(canvas);
  62. canvas.drawColor(0xEFeffff );
  63. Paint p = mPaint;
  64. Paint p2 = mPathPaint;
  65. p.setTextAlign(Paint.Align.CENTER);
  66. if  (index == -1 )
  67. return ;
  68. p2.setTextAlign(Paint.Align.CENTER);
  69. // 先画当前行,之后再画他的前面和后面,这样就保持当前行在中间的位置
  70. canvas.drawText(list.get(index).getContent(), mX, middleY, p2);
  71. float  tempY = middleY;
  72. // 画出本句之前的句子
  73. for  (int  i = index - 1 ; i >= 0 ; i--) {
  74. // Sentence sen = list.get(i);
  75. // 向上推移
  76. tempY = tempY - DY;
  77. if  (tempY < 0 ) {
  78. break ;
  79. }
  80. canvas.drawText(list.get(i).getContent(), mX, tempY, p);
  81. // canvas.translate(0, DY);
  82. }
  83. tempY = middleY;
  84. // 画出本句之后的句子
  85. for  (int  i = index + 1 ; i < list.size(); i++) {
  86. // 往下推移
  87. tempY = tempY + DY;
  88. if  (tempY > mY) {
  89. break ;
  90. }
  91. canvas.drawText(list.get(i).getContent(), mX, tempY, p);
  92. // canvas.translate(0, DY);
  93. }
  94. }
  95. protected  void  onSizeChanged(int  w, int  h, int  ow, int  oh) {
  96. super .onSizeChanged(w, h, ow, oh);
  97. mX = w * 0 .5f; // remember the center of the screen
  98. mY = h;
  99. middleY = h * 0 .5f;
  100. }
  101. //
  102. /**
  103. * @param time
  104. *            当前歌词的时间轴
  105. *
  106. * @return currentDunringTime 歌词只需的时间
  107. */
  108. public  long  updateIndex(long  time) {
  109. // 歌词序号
  110. index = mLyric.getNowSentenceIndex(time);
  111. if  (index == -1 )
  112. return  -1 ;
  113. Sentence sen = list.get(index);
  114. // 返回歌词持续的时间,在这段时间内sleep
  115. return  currentDunringTime = sen.getDuring();
  116. }
  117. }

package ru.org.piaozhiye.lyric; import java.io.File; import java.util.List; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Typeface; import android.util.AttributeSet; import android.widget.TextView; /** * @author root * */ public class LyricView extends TextView { private Paint mPaint; private float mX; private static Lyric mLyric; private Paint mPathPaint; public String test = "test"; public int index = 0; private List<Sentence> list; public float mTouchHistoryY; private int mY; private long currentDunringTime; // 当前行歌词持续的时间,用该时间来sleep private float middleY;// y轴中间 private static final int DY = 50; // 每一行的间隔 public LyricView(Context context) { super(context); init(); } public LyricView(Context context, AttributeSet attr) { super(context, attr); init(); } public LyricView(Context context, AttributeSet attr, int i) { super(context, attr, i); init(); } private void init() { setFocusable(true); PlayListItem pli = new PlayListItem("Because Of You", "/sdcard/MP3/Because Of You.mp3", 0L, true); mLyric = new Lyric(new File("/sdcard/MP3/Because Of You.lrc"), pli); list = mLyric.list; // 非高亮部分 mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setTextSize(22); mPaint.setColor(Color.WHITE); mPaint.setTypeface(Typeface.SERIF); // 高亮部分 当前歌词 mPathPaint = new Paint(); mPathPaint.setAntiAlias(true); mPathPaint.setColor(Color.RED); mPathPaint.setTextSize(22); mPathPaint.setTypeface(Typeface.SANS_SERIF); } protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(0xEFeffff); Paint p = mPaint; Paint p2 = mPathPaint; p.setTextAlign(Paint.Align.CENTER); if (index == -1) return; p2.setTextAlign(Paint.Align.CENTER); // 先画当前行,之后再画他的前面和后面,这样就保持当前行在中间的位置 canvas.drawText(list.get(index).getContent(), mX, middleY, p2); float tempY = middleY; // 画出本句之前的句子 for (int i = index - 1; i >= 0; i--) { // Sentence sen = list.get(i); // 向上推移 tempY = tempY - DY; if (tempY < 0) { break; } canvas.drawText(list.get(i).getContent(), mX, tempY, p); // canvas.translate(0, DY); } tempY = middleY; // 画出本句之后的句子 for (int i = index + 1; i < list.size(); i++) { // 往下推移 tempY = tempY + DY; if (tempY > mY) { break; } canvas.drawText(list.get(i).getContent(), mX, tempY, p); // canvas.translate(0, DY); } } protected void onSizeChanged(int w, int h, int ow, int oh) { super.onSizeChanged(w, h, ow, oh); mX = w * 0.5f; // remember the center of the screen mY = h; middleY = h * 0.5f; } // /** * @param time * 当前歌词的时间轴 * * @return currentDunringTime 歌词只需的时间 */ public long updateIndex(long time) { // 歌词序号 index = mLyric.getNowSentenceIndex(time); if (index == -1) return -1; Sentence sen = list.get(index); // 返回歌词持续的时间,在这段时间内sleep return currentDunringTime = sen.getDuring(); } }

剩下的就是使用他了。就是取出歌词的index,和该行歌词持续的时间进行sleep。

view plain copy to clipboard print ?
  1. package ru.org.piaozhiye;
  2. import java.io.IOException;
  3. import ru.org.piaozhiye.lyric.LyricView;
  4. import android.app.Activity;
  5. import android.media.MediaPlayer;
  6. import android.os.Bundle;
  7. import android.os.Handler;
  8. public  class  LyricDemo extends Activity {
  9. private  MediaPlayer mp;
  10. private  LyricView lyricView;
  11. private  String path = "/sdcard/MP3/Because Of You.mp3" ;
  12. /** Called when the activity is first created. */
  13. @Override
  14. public  void  onCreate(Bundle savedInstanceState) {
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.main);
  17. lyricView = (LyricView) findViewById(R.id.audio_lrc);
  18. mp = new  MediaPlayer();
  19. mp.reset();
  20. try  {
  21. mp.setDataSource(path);
  22. mp.prepare();
  23. } catch  (IllegalArgumentException e) {
  24. // TODO Auto-generated catch block
  25. e.printStackTrace();
  26. } catch  (IllegalStateException e) {
  27. // TODO Auto-generated catch block
  28. e.printStackTrace();
  29. } catch  (IOException e) {
  30. // TODO Auto-generated catch block
  31. e.printStackTrace();
  32. }
  33. mp.start();
  34. new  Thread(new  UIUpdateThread()).start();
  35. }
  36. class  UIUpdateThread implements Runnable {
  37. long  time = 100; // 开始 的时间,不能为零,否则前面几句歌词没有显示出来
  38. public  void  run() {
  39. while  (mp.isPlaying()) {
  40. long  sleeptime = lyricView.updateIndex(time);
  41. time += sleeptime;
  42. mHandler.post(mUpdateResults);
  43. if  (sleeptime == -1)
  44. return ;
  45. try  {
  46. Thread.sleep(sleeptime);
  47. } catch  (InterruptedException e) {
  48. // TODO Auto-generated catch block
  49. e.printStackTrace();
  50. }
  51. }
  52. }
  53. }
  54. Handler mHandler = new  Handler();
  55. Runnable mUpdateResults = new  Runnable() {
  56. public  void  run() {
  57. lyricView.invalidate(); // 更新视图
  58. }
  59. };
  60. }

package ru.org.piaozhiye; import java.io.IOException; import ru.org.piaozhiye.lyric.LyricView; import android.app.Activity; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Handler; public class LyricDemo extends Activity { private MediaPlayer mp; private LyricView lyricView; private String path = "/sdcard/MP3/Because Of You.mp3"; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); lyricView = (LyricView) findViewById(R.id.audio_lrc); mp = new MediaPlayer(); mp.reset(); try { mp.setDataSource(path); mp.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(); } mp.start(); new Thread(new UIUpdateThread()).start(); } class UIUpdateThread implements Runnable { long time = 100; // 开始 的时间,不能为零,否则前面几句歌词没有显示出来 public void run() { while (mp.isPlaying()) { long sleeptime = lyricView.updateIndex(time); time += sleeptime; mHandler.post(mUpdateResults); if (sleeptime == -1) return; try { Thread.sleep(sleeptime); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } Handler mHandler = new Handler(); Runnable mUpdateResults = new Runnable() { public void run() { lyricView.invalidate(); // 更新视图 } }; }

整个project的源码。包括yoyoplayer的解析lyric部分代码。

http://download.csdn.net/source/3186718

android实现歌词的自动滚动相关推荐

  1. android文字自动滚动,Android TextView文字横向自动滚动(跑马灯)

    TextView实现文字滚动需要以下几个要点: 1.文字长度长于可显示范围:android:singleLine="true" 2.设置可滚到,或显示样式:android:elli ...

  2. Android TextView文字横向自动滚动(跑马灯)

    TextView实现文字滚动需要以下几个要点: 1.文字长度长于可显示范围:android:singleLine="true" 2.设置可滚到,或显示样式:android:elli ...

  3. 实现歌词效果自动滚动_只需五步,专业Pr软件实现视频歌词渐变色效果,你学会了吗?...

    大家好,现如今短视频行业的飞速发展,造就视频的花样百出,形成不同视角冲击,其中音乐播放器的歌词渐变效果是我们平常接触最多的一个效果(如下图),今天我就来给大家讲解如何用Premiere软件快速简单制作 ...

  4. android开发歌词滑动效果_android实现歌词自动滚动效果

    最近在做Android 的MP3播放的项目,要实现歌词的自动滚动,以及同步显示. lyric的歌词解析主要用yoyoplayer里面的,显示部分参考了这里 ,这里只是模拟MP3歌词的滚动. 先上一下效 ...

  5. android文字多行滚动显示,Android TextView多行文本滚动实现

    Android中我们为了实现文本的滚动可以在ScrollView中嵌入一个TextView,其实TextView自己也可以实现多行滚动的,毕竟ScrollView必须只能有一个直接的子类布局.只要在l ...

  6. android开发歌词滑动效果_android 实现歌词自动滚动+手指顺畅拖动

    需求: 1.歌词可以跟随播放进度进行自动滑动: 2.可以手指进行歌词顺畅滑动: 3.当前歌词高亮,且置于屏幕的中心: 实现方式一: 也是网上可以搜到的做多的方式:自定义view,继承textview; ...

  7. android高仿天天动听,Android仿天天动听歌曲自动滚动view

    最近项目中要做一个类似天天动听歌曲自动滚动行数的效果.首先自己想了下Android要滚动的那就是scroller类或者scrollto.scrollby结合了,或者view.layout()方法,或者 ...

  8. android开发歌词滑动效果_Android应用开发--MP3音乐播放器滚动歌词实现

    [android]代码库2013年6月2日 简.美音乐播放器开发记录 -----主题 这篇博客的主题是:"滚动歌词的实现" 要的效果如下: ----实现过程 1. 建立歌词内容实体 ...

  9. android仿天天动听歌曲自动滚动view

    转载请标明出处: http://blog.csdn.net/iamzgx/article/details/51448620: 本文出自:[iGoach的博客] 背景 最近项目中要做一个类似天天动听歌曲 ...

最新文章

  1. PHP for Linux之xml2-config这个文件没找到
  2. map mybatis 的字段返回0_Mybatis 你踩过坑吗?
  3. Android之React native的介绍和入门指南
  4. PIC18F452之1602自定义字符
  5. bootstrap轮播图 原点变为方块_Brother兄弟机床原点设定方法
  6. Nutanix的野心可不小!
  7. android 人脸检测_Android人脸检测
  8. 李彦宏宣布百度架构调整:智能云事业部升级
  9. 遗传算法python实现
  10. 编译原理(紫龙书)第2版习题答案
  11. [视频基础]流媒体码流、分辨率、采样率、比特率、gop、qp、fps、cvbr概念理解
  12. java出名的外国文献_三大牛人看外国文献的方法(搜索无重复) - 论文投稿 - 小木虫 - 学术 科研 互动社区...
  13. BeanUtils的populate方法之日期处理
  14. 基于麻雀算法的无人机航迹规划 - 附代码
  15. 深度学习平台demo(一)- C#如何调用python文件
  16. 远道知学院| 名下有很多子公司,每个都要独立申请知识产权吗?
  17. Python中杨辉三角的理解(廖雪峰教程例)
  18. 第一天,初了解锐捷网络
  19. 使用expdp导出数据
  20. c语言初学-const指针

热门文章

  1. LOL雨鱼ADC一键走砍清兵工具v10.14
  2. 【微信video视频播放】video标签
  3. excel柱形图/条形图怎能给正负值填充不同的颜色
  4. 《人生只有一次,去做自己喜欢的事》读书笔记
  5. 净化自己的内心,扫除内心的尘埃
  6. Android开发需要学什么,技术实现
  7. 直播间几万人助力砍价到小数点后6位,依旧失败,拼多多再陷“砍价”风波
  8. android 小游戏心得、,iOS/安卓版《辐射:避难所(Fallout Shelter)》攻略心得:玩法要点详解与心得技巧...
  9. 如何用计算机给闺蜜表白,闺蜜情话最暖心短句50句
  10. slice与split的区别