android实现歌词自动滚动效果
作者:javaxinkule 发布时间:2022-03-16 17:09:10
标签:android,滚动
最近在做Android 的MP3播放的项目,要实现歌词的自动滚动,以及同步显示。
lyric的歌词解析主要用yoyoplayer里面的,显示部分参考了这里 ,这里只是模拟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();
}
}
剩下的就是使用他了。就是取出歌词的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(); // 更新视图
}
};
}
整个project的源码。包括yoyoplayer的解析lyric部分代码。
来源:https://blog.csdn.net/javaxinkule/article/details/53224896


猜你喜欢
- layout<?xml version="1.0"?>-<LinearLayout android:p
- 自定义注解1) 先定义布局文件注入//注解的作用域在类上@Target(ElementType.TYPE)//让保持性策略为运行时态,将注解
- 最近重构了一下我的存档框架。我在这里对实现方法进行简单的解析。注意这里主要演示算法,所以,效率上并不是最佳。一个游戏中,可能有成百上千个物体
- C#异常处理总结及简单实例一、异常处理的理解?异常处理是指程序在运行过程中,发生错误会导致程序退出,这种错误,就叫做异常。因此处理这种错误,
- 首先引入依赖 implementation 'com.github.bumptech.glide:glid
- 导航是指支持用户导航、进入和退出应用中不同内容片段的交互。Android Jetpack 的导航组件可帮助您实现导航,无论是简单的按钮点击,
- 所谓前人栽树,后人乘凉,在此感谢博主的贡献。 原文:边缘凹凸的卡劵效果先上效果图:我实现的效果和原博主实现的效果是不一样的,我是左右边缘凹凸
- 在upload.jsp页面中将多个文件域对象命名为相同的名字,这样在action中就可以将多个文件域解析成一个数组,数组的大小就是文件域的个
- 如题,有时候看见一个布局写上几百行看上去会非常吃力麻烦,这时候抽取控件样式很有必要了, Android Studio提供了抽取Style样式
- 前言社区内容经常会有插入链接的需要,这时就产生了对链接的UI和点击交互的需求,我们在微博中也经常会在列表页面和详情页面看到。下边我们就此功能
- 一、简述首先,Java 8引入了java.time.LocalDate来表示一个没有时间的日期。其次,使用Java 8版本,还需要更新jav
- 一.EventBus概述 1.EventBus的三要素EventBus有三个主要的元素需要我们先了解一下:Event:事件,可以是任意类型的
- 全面总结Android Service的使用方法,具体内容如下1、Service的种类按运行地点分类:其实remote服务还是很少见的,并且
- 本文实例讲述了C#检测远程计算机端口是否打开的方法。分享给大家供大家参考。具体分析如下:这段C#代码用于检测远程计算机的3389端口是否处理
- 重写 equals()方法 和 hashCode()方法最近看了学习了集合的简单的知识,碰到了讲解 Set 的部分,感觉很好奇,这里对于 S
- 今天给大家介绍一下如何实现一款简约时尚的安卓登陆界面。大家先看一下效果图当用户输入时动态出现删除按钮 现在先罗列一下技术点:1.如何使用圆角
- cookie和session的比较一、对于cookie:①cookie是创建于服务器端②cookie保存在浏览器端③cookie的生命周期可
- 记录查找自动组拼SQL语句的过程首先在BaseMapper其中的一个方法下打个断点在断点显示的值栏找到相关的SQL发现SQL语句在Mappe
- 本文实例为大家分享了Unity创建平铺网格地图的具体代码,供大家参考,具体内容如下创建预制件先拖进场景,再从层级拖回资源选中源图像文件,设置
- 多线程编程多线程编程模式.NET 中,有三种异步编程模式,分别是基于任务的异步模式(TAP)、基于事件的异步模式(EAP)、异步编程模式(A