android实现歌词的自动滚动
最近在做android 的MP3播放的项目,要实现歌词的自动滚动,以及同步显示。
lyric的歌词解析主要用yoyoplayer里面的,
显示部分参考了http://ishelf.iteye.com/blog/740402 ,这里只是模拟MP3歌词的滚动。
先上一下效果图:
滚动实现的代码其实也简单。显示画出当前时间点的歌词,然后再分别画出改歌词后面和前面的歌词,前面的部分往上推移,后面的部分往下推移,这样就保持了当前时间歌词在中间。
代码如下 LyricView,相关信息在注释了标明了。
- 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();
- }
- }
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。
- 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(); // 更新视图
- }
- };
- }
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实现歌词的自动滚动相关推荐
- android文字自动滚动,Android TextView文字横向自动滚动(跑马灯)
TextView实现文字滚动需要以下几个要点: 1.文字长度长于可显示范围:android:singleLine="true" 2.设置可滚到,或显示样式:android:elli ...
- Android TextView文字横向自动滚动(跑马灯)
TextView实现文字滚动需要以下几个要点: 1.文字长度长于可显示范围:android:singleLine="true" 2.设置可滚到,或显示样式:android:elli ...
- 实现歌词效果自动滚动_只需五步,专业Pr软件实现视频歌词渐变色效果,你学会了吗?...
大家好,现如今短视频行业的飞速发展,造就视频的花样百出,形成不同视角冲击,其中音乐播放器的歌词渐变效果是我们平常接触最多的一个效果(如下图),今天我就来给大家讲解如何用Premiere软件快速简单制作 ...
- android开发歌词滑动效果_android实现歌词自动滚动效果
最近在做Android 的MP3播放的项目,要实现歌词的自动滚动,以及同步显示. lyric的歌词解析主要用yoyoplayer里面的,显示部分参考了这里 ,这里只是模拟MP3歌词的滚动. 先上一下效 ...
- android文字多行滚动显示,Android TextView多行文本滚动实现
Android中我们为了实现文本的滚动可以在ScrollView中嵌入一个TextView,其实TextView自己也可以实现多行滚动的,毕竟ScrollView必须只能有一个直接的子类布局.只要在l ...
- android开发歌词滑动效果_android 实现歌词自动滚动+手指顺畅拖动
需求: 1.歌词可以跟随播放进度进行自动滑动: 2.可以手指进行歌词顺畅滑动: 3.当前歌词高亮,且置于屏幕的中心: 实现方式一: 也是网上可以搜到的做多的方式:自定义view,继承textview; ...
- android高仿天天动听,Android仿天天动听歌曲自动滚动view
最近项目中要做一个类似天天动听歌曲自动滚动行数的效果.首先自己想了下Android要滚动的那就是scroller类或者scrollto.scrollby结合了,或者view.layout()方法,或者 ...
- android开发歌词滑动效果_Android应用开发--MP3音乐播放器滚动歌词实现
[android]代码库2013年6月2日 简.美音乐播放器开发记录 -----主题 这篇博客的主题是:"滚动歌词的实现" 要的效果如下: ----实现过程 1. 建立歌词内容实体 ...
- android仿天天动听歌曲自动滚动view
转载请标明出处: http://blog.csdn.net/iamzgx/article/details/51448620: 本文出自:[iGoach的博客] 背景 最近项目中要做一个类似天天动听歌曲 ...
最新文章
- PHP for Linux之xml2-config这个文件没找到
- map mybatis 的字段返回0_Mybatis 你踩过坑吗?
- Android之React native的介绍和入门指南
- PIC18F452之1602自定义字符
- bootstrap轮播图 原点变为方块_Brother兄弟机床原点设定方法
- Nutanix的野心可不小!
- android 人脸检测_Android人脸检测
- 李彦宏宣布百度架构调整:智能云事业部升级
- 遗传算法python实现
- 编译原理(紫龙书)第2版习题答案
- [视频基础]流媒体码流、分辨率、采样率、比特率、gop、qp、fps、cvbr概念理解
- java出名的外国文献_三大牛人看外国文献的方法(搜索无重复) - 论文投稿 - 小木虫 - 学术 科研 互动社区...
- BeanUtils的populate方法之日期处理
- 基于麻雀算法的无人机航迹规划 - 附代码
- 深度学习平台demo(一)- C#如何调用python文件
- 远道知学院| 名下有很多子公司,每个都要独立申请知识产权吗?
- Python中杨辉三角的理解(廖雪峰教程例)
- 第一天,初了解锐捷网络
- 使用expdp导出数据
- c语言初学-const指针
热门文章
- LOL雨鱼ADC一键走砍清兵工具v10.14
- 【微信video视频播放】video标签
- excel柱形图/条形图怎能给正负值填充不同的颜色
- 《人生只有一次,去做自己喜欢的事》读书笔记
- 净化自己的内心,扫除内心的尘埃
- Android开发需要学什么,技术实现
- 直播间几万人助力砍价到小数点后6位,依旧失败,拼多多再陷“砍价”风波
- android 小游戏心得、,iOS/安卓版《辐射:避难所(Fallout Shelter)》攻略心得:玩法要点详解与心得技巧...
- 如何用计算机给闺蜜表白,闺蜜情话最暖心短句50句
- slice与split的区别