parent
eccd8b4301
commit
6c7b150b13
@ -0,0 +1,29 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<Objective-C-extensions>
|
||||
<file>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||
</file>
|
||||
<class>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||
</class>
|
||||
<extensions>
|
||||
<pair source="cpp" header="h" fileNamingConvention="NONE" />
|
||||
<pair source="c" header="h" fileNamingConvention="NONE" />
|
||||
</extensions>
|
||||
</Objective-C-extensions>
|
||||
</code_scheme>
|
||||
</component>
|
@ -0,0 +1,49 @@
|
||||
package com.example.musicplayer.entiy;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* author : 残渊
|
||||
* time : 2019/03/18
|
||||
* desc : 歌词实体类
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
public class LrcBean {
|
||||
private String lrc;
|
||||
private long start;
|
||||
private long end;
|
||||
|
||||
public LrcBean() {
|
||||
}
|
||||
|
||||
public LrcBean(String text, long start, long end) {
|
||||
this.lrc = text;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public String getLrc() {
|
||||
return lrc;
|
||||
}
|
||||
|
||||
public void setLrc(String lrc) {
|
||||
this.lrc = lrc;
|
||||
}
|
||||
|
||||
public long getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(long start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public long getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public void setEnd(long end) {
|
||||
this.end = end;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,90 @@
|
||||
package com.example.musicplayer.util;
|
||||
|
||||
import com.example.musicplayer.entiy.LrcBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* author : 残渊
|
||||
* time : 2019/03/18
|
||||
* desc : 歌词工具类
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
public class LrcUtil {
|
||||
/**
|
||||
* 传入的参数为标准歌词字符串
|
||||
*
|
||||
* @param lrcStr
|
||||
* @return
|
||||
*/
|
||||
public static List<LrcBean> parseStr2List(String lrcStr) {
|
||||
List<LrcBean> list = new ArrayList<>();
|
||||
String lrcText = lrcStr.replaceAll(":", ":")
|
||||
.replaceAll("'", "'")
|
||||
.replaceAll(" ", "\n")
|
||||
.replaceAll(".", ".")
|
||||
.replaceAll(" ", " ")
|
||||
.replaceAll("-", "-")
|
||||
.replaceAll(" ", "\r")
|
||||
.replaceAll("'", "'");
|
||||
String[] split = lrcText.split("\n");
|
||||
for (int i = 4; i < split.length; i++) {
|
||||
String lrc = split[i];
|
||||
if (lrc.contains(".")) {
|
||||
String min = lrc.substring(lrc.indexOf("[") + 1, lrc.indexOf("[") + 3);
|
||||
String seconds = lrc.substring(lrc.indexOf(":") + 1, lrc.indexOf(":") + 3);
|
||||
String mills = lrc.substring(lrc.indexOf(".") + 1, lrc.indexOf(".") + 3);
|
||||
long startTime = Long.valueOf(min) * 60 * 1000 + Long.valueOf(seconds) * 1000 + Long.valueOf(mills) * 10;
|
||||
String text = lrc.substring(lrc.indexOf("]") + 1);
|
||||
if (text.equals("") || text == null) continue;
|
||||
if (i == 5) {
|
||||
int first = text.indexOf("(");
|
||||
int second = text.indexOf("(", first + 1);
|
||||
String textFront = null;
|
||||
String textBehind = null;
|
||||
boolean isTwo = true;
|
||||
boolean isOne = true;
|
||||
try {
|
||||
textFront = text.substring(0, first);
|
||||
}catch (StringIndexOutOfBoundsException e){
|
||||
isOne = false;
|
||||
}
|
||||
try {
|
||||
textBehind = text.substring(first + 1, second);
|
||||
} catch (StringIndexOutOfBoundsException e) {
|
||||
isTwo = false;
|
||||
}
|
||||
LrcBean lrcBean1 = new LrcBean();
|
||||
lrcBean1.setStart(startTime);
|
||||
if(isOne) {
|
||||
lrcBean1.setLrc(textFront);
|
||||
} else {
|
||||
lrcBean1.setLrc(text);
|
||||
}
|
||||
list.add(lrcBean1);
|
||||
if (isTwo) {
|
||||
LrcBean lrcBean2 = new LrcBean();
|
||||
lrcBean2.setStart(startTime);
|
||||
lrcBean2.setLrc(textBehind);
|
||||
list.add(lrcBean2);
|
||||
}
|
||||
} else {
|
||||
LrcBean lrcBean = new LrcBean();
|
||||
lrcBean.setStart(startTime);
|
||||
lrcBean.setLrc(text);
|
||||
list.add(lrcBean);
|
||||
}
|
||||
if (list.size() > 1) {
|
||||
list.get(list.size() - 2).setEnd(startTime);
|
||||
}
|
||||
if (i == split.length - 1) {
|
||||
list.get(list.size() - 1).setEnd(startTime + 100000);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
package com.example.musicplayer.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.media.MediaPlayer;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import com.example.musicplayer.R;
|
||||
import com.example.musicplayer.entiy.LrcBean;
|
||||
import com.example.musicplayer.util.LrcUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* author : 残渊
|
||||
* time : 2019/03/18
|
||||
* desc : 自定义歌词界面
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
public class LrcView extends View {
|
||||
|
||||
private List<LrcBean> list;
|
||||
private Paint gPaint;
|
||||
private Paint hPaint;
|
||||
private int width = 0, height = 0;
|
||||
private int currentPosition = 0;
|
||||
private MediaPlayer player;
|
||||
private int lastPosition = 0;
|
||||
private int highLineColor;
|
||||
private int lrcTextSize;
|
||||
private int lrcColor;
|
||||
private int mode = 0;
|
||||
public final static int KARAOKE = 1;
|
||||
|
||||
public void setHighLineColor(int highLineColor) {
|
||||
this.highLineColor = highLineColor;
|
||||
}
|
||||
|
||||
public void setLrcColor(int lrcColor) {
|
||||
this.lrcColor = lrcColor;
|
||||
}
|
||||
|
||||
public void setMode(int mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public void setPlayer(MediaPlayer player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* 标准歌词字符串
|
||||
*
|
||||
* @param lrc
|
||||
*/
|
||||
public void setLrc(String lrc) {
|
||||
list = LrcUtil.parseStr2List(lrc);
|
||||
}
|
||||
|
||||
public LrcView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public LrcView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public LrcView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LrcView);
|
||||
highLineColor = ta.getColor(R.styleable.LrcView_hignLineColor, getResources().getColor(R.color.green));
|
||||
lrcColor = ta.getColor(R.styleable.LrcView_lrcColor, getResources().getColor(android.R.color.darker_gray));
|
||||
float densityText = getResources().getDisplayMetrics().scaledDensity;
|
||||
lrcTextSize = ta.getDimensionPixelSize(R.styleable.LrcView_lrcTextSize,(int)(16*densityText));
|
||||
mode = ta.getInt(R.styleable.LrcView_lrcMode,mode);
|
||||
ta.recycle();
|
||||
gPaint = new Paint();
|
||||
gPaint.setAntiAlias(true);
|
||||
gPaint.setColor(lrcColor);
|
||||
gPaint.setTextSize(lrcTextSize);
|
||||
gPaint.setTextAlign(Paint.Align.CENTER);
|
||||
hPaint = new Paint();
|
||||
hPaint.setAntiAlias(true);
|
||||
hPaint.setColor(highLineColor);
|
||||
hPaint.setTextSize(lrcTextSize);
|
||||
hPaint.setTextAlign(Paint.Align.CENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (width == 0 || height == 0) {
|
||||
width = getMeasuredWidth();
|
||||
height = getMeasuredHeight();
|
||||
}
|
||||
if (list == null || list.size() == 0) {
|
||||
canvas.drawText("暂无歌词", width / 2, height / 2, gPaint);
|
||||
return;
|
||||
}
|
||||
|
||||
getCurrentPosition();
|
||||
int currentMillis = player.getCurrentPosition();
|
||||
drawLrc2(canvas, currentMillis);
|
||||
long start = list.get(currentPosition).getStart();
|
||||
float v = (currentMillis - start) > 500 ? currentPosition * 120 : lastPosition * 120 + (currentPosition - lastPosition) * 120 * ((currentMillis - start) / 500f);
|
||||
setScrollY((int) v);
|
||||
if (getScrollY() == currentPosition * 120) {
|
||||
lastPosition = currentPosition;
|
||||
}
|
||||
postInvalidateDelayed(100);
|
||||
}
|
||||
|
||||
private void drawLrc2(Canvas canvas, int currentMillis) {
|
||||
if (mode == 0) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (i == currentPosition) {
|
||||
canvas.drawText(list.get(i).getLrc(), width / 2, height / 2 + 120 * i, hPaint);
|
||||
} else {
|
||||
canvas.drawText(list.get(i).getLrc(), width / 2, height / 2 + 120 * i, gPaint);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
canvas.drawText(list.get(i).getLrc(), width / 2, height / 2 + 80 * i, gPaint);
|
||||
}
|
||||
String highLineLrc = list.get(currentPosition).getLrc();
|
||||
int highLineWidth = (int) gPaint.measureText(highLineLrc);
|
||||
int leftOffset = (width - highLineWidth) / 2;
|
||||
LrcBean lrcBean = list.get(currentPosition);
|
||||
long start = lrcBean.getStart();
|
||||
long end = lrcBean.getEnd();
|
||||
int i = (int) ((currentMillis - start) * 1.0f / (end - start) * highLineWidth);
|
||||
if (i > 0) {
|
||||
Bitmap textBitmap = Bitmap.createBitmap(i, 80, Bitmap.Config.ARGB_8888);
|
||||
Canvas textCanvas = new Canvas(textBitmap);
|
||||
textCanvas.drawText(highLineLrc, highLineWidth / 2, 80, hPaint);
|
||||
canvas.drawBitmap(textBitmap, leftOffset, height / 2 + 80 * (currentPosition - 1), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void init() {
|
||||
currentPosition = 0;
|
||||
lastPosition = 0;
|
||||
setScrollY(0);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void drawLrc1(Canvas canvas) {
|
||||
String text = list.get(currentPosition).getLrc();
|
||||
canvas.drawText(text, width / 2, height / 2, hPaint);
|
||||
|
||||
for (int i = 1; i < 10; i++) {
|
||||
int index = currentPosition - i;
|
||||
if (index > -1) {
|
||||
canvas.drawText(list.get(index).getLrc(), width / 2, height / 2 - 100 * i, gPaint);
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < 10; i++) {
|
||||
int index = currentPosition + i;
|
||||
if (index < list.size()) {
|
||||
canvas.drawText(list.get(index).getLrc(), width / 2, height / 2 + 100 * i, gPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void getCurrentPosition() {
|
||||
try {
|
||||
int currentMillis = player.getCurrentPosition();
|
||||
if (currentMillis < list.get(0).getStart()) {
|
||||
currentPosition = 0;
|
||||
return;
|
||||
}
|
||||
if (currentMillis > list.get(list.size() - 1).getStart()) {
|
||||
currentPosition = list.size() - 1;
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (currentMillis >= list.get(i).getStart() && currentMillis < list.get(i).getEnd()) {
|
||||
currentPosition = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
postInvalidateDelayed(100);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue