From 57fe689f1862ad0fda96b2e9eb054be6a7c9425d Mon Sep 17 00:00:00 2001
From: Runt <qingingrunt2010@qq.com>
Date: Wed, 04 May 2022 12:53:14 +0000
Subject: [PATCH] 歌词显示时间控制
---
app/src/main/res/values/themes.xml | 10
app/src/main/java/com/auto/lyric/base/activities/BaseTitleBarActivity.java | 3
app/src/main/java/com/auto/lyric/data/SendText.java | 14 +
app/src/main/java/com/auto/lyric/data/TextBean.java | 14 +
app/src/main/java/com/auto/lyric/service/FloatingWindowService.java | 156 ++++++++++-
app/src/main/java/com/auto/lyric/base/activities/BaseActivity.java | 13 -
app/src/main/java/com/auto/lyric/MainActivity.java | 77 +++--
app/src/main/java/com/auto/lyric/data/LyricObject.java | 11
app/src/main/res/layout/float_view.xml | 23 +
app/src/main/res/layout/activity_main.xml | 1
app/src/main/java/com/auto/lyric/data/LyricServer.java | 143 +++++++++++
app/src/main/java/com/auto/lyric/widgets/Sentence.java | 5
app/src/main/java/com/auto/lyric/widgets/LyricView.java | 310 ++++++++++++++---------
13 files changed, 584 insertions(+), 196 deletions(-)
diff --git a/app/src/main/java/com/auto/lyric/MainActivity.java b/app/src/main/java/com/auto/lyric/MainActivity.java
index 462bbc8..121b6f9 100644
--- a/app/src/main/java/com/auto/lyric/MainActivity.java
+++ b/app/src/main/java/com/auto/lyric/MainActivity.java
@@ -1,27 +1,26 @@
package com.auto.lyric;
import android.content.Intent;
-import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
-import android.os.Handler;
-import android.os.Message;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-
-import androidx.annotation.NonNull;
+import android.widget.Toast;
import com.auto.lyric.base.activities.BaseActivity;
+import com.auto.lyric.data.LyricServer;
+import com.auto.lyric.data.TextBean;
import com.auto.lyric.databinding.ActivityMainBinding;
-import com.auto.lyric.databinding.FloatViewBinding;
import com.auto.lyric.service.AutoInputService;
import com.auto.lyric.service.FloatingWindowService;
import com.auto.lyric.vm.MainViewModel;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.regex.Pattern;
public class MainActivity extends BaseActivity<ActivityMainBinding, MainViewModel> {
@@ -33,10 +32,38 @@
Intent floatService = new Intent(getApplicationContext(), FloatingWindowService.class);
binding.button.setOnClickListener(v -> {
+ if(binding.edit.getText().toString().trim().length() == 0){
+ Toast.makeText(this,"请输入文本", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ ArrayList<TextBean> arrayList = new ArrayList<>();//解析的文本数据
+ SimpleDateFormat msFormat = new SimpleDateFormat("mm:ss.SSS");
+ String[] strings = binding.edit.getText().toString().split("\n");
+ for(String text : strings){
+ int index = text.indexOf("]");
+ if(index < 8 ){
+ continue;
+ }
+ String regex = "(?<=\\])";
+ Pattern compile = Pattern.compile(regex);
+ String[] split = compile.split(text,2);
+ long wait = 0;
+ try {
+ wait = 28800000 + msFormat.parse(split[0].replace("[","").replace("]","")).getTime();
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ arrayList.add(new TextBean(wait,split[1]));
+ }
+ if(arrayList.size() == 0){
+ return;
+ }
+
+ LyricServer.read(Arrays.asList(strings));
//申请权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//开启悬浮窗
- /* if(!Settings.canDrawOverlays(getApplicationContext())) {
+ if(!Settings.canDrawOverlays(getApplicationContext())) {
//启动Activity让用户授权
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
@@ -47,10 +74,8 @@
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
startActivity(intent);
}else{//开启监听服务
- //startService(floatService);
- }*/
- startService(floatService);
- //showFloatView();
+ startService(floatService);
+ }
}
});
}
@@ -93,27 +118,5 @@
return false;
}
- private void showFloatView(){
-
-
- //View view = LayoutInflater.from(this).inflate(R.layout.float_view,null);
- FloatViewBinding binding = FloatViewBinding.inflate(getLayoutInflater());
- WindowManager manager = (WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE);
- WindowManager.LayoutParams params = new WindowManager.LayoutParams();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
- }else {
- params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
- }
- params.format = PixelFormat.RGBA_8888;
- params.gravity = Gravity.CENTER;
- params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- params.width = WindowManager.LayoutParams.MATCH_PARENT;
- params.height = WindowManager.LayoutParams.WRAP_CONTENT;
- binding.btnBack.setOnClickListener(v ->{
- stopService(new Intent(this,this.getClass()));
- });
- manager.addView(binding.getRoot(),params);
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/auto/lyric/base/activities/BaseActivity.java b/app/src/main/java/com/auto/lyric/base/activities/BaseActivity.java
index 83b2702..df0058d 100644
--- a/app/src/main/java/com/auto/lyric/base/activities/BaseActivity.java
+++ b/app/src/main/java/com/auto/lyric/base/activities/BaseActivity.java
@@ -243,19 +243,6 @@
InputMethodManager.HIDE_NOT_ALWAYS);
}
}
- /**
- * 状态栏高度
- * @return
- */
- public int getStatusBarHeight() {
- int result = 0;
- int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");
- if (resId > 0) {
- result = getResources().getDimensionPixelOffset(resId);
- }
- return result;
- }
-
long mExitTime= 0 ;
/**
diff --git a/app/src/main/java/com/auto/lyric/base/activities/BaseTitleBarActivity.java b/app/src/main/java/com/auto/lyric/base/activities/BaseTitleBarActivity.java
index 68fffeb..3ea2dda 100644
--- a/app/src/main/java/com/auto/lyric/base/activities/BaseTitleBarActivity.java
+++ b/app/src/main/java/com/auto/lyric/base/activities/BaseTitleBarActivity.java
@@ -8,6 +8,7 @@
import androidx.viewbinding.ViewBinding;
import com.auto.lyric.base.model.BaseViewModel;
+import com.auto.lyric.util.DeviceUtil;
import com.auto.lyric.widgets.TitleBarView;
@@ -54,7 +55,7 @@
public void setStatusBarTransparent(boolean isBlack) {
super.setStatusBarTransparent(isBlack);
final ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) titleBarView.getLayoutParams();
- layoutParams.topMargin = layoutParams.topMargin+getStatusBarHeight();
+ layoutParams.topMargin = layoutParams.topMargin+ DeviceUtil.getStatusBarHeight(this);
titleBarView.setLayoutParams(layoutParams);
}
diff --git a/app/src/main/java/com/auto/lyric/data/LyricObject.java b/app/src/main/java/com/auto/lyric/data/LyricObject.java
new file mode 100644
index 0000000..d8379d7
--- /dev/null
+++ b/app/src/main/java/com/auto/lyric/data/LyricObject.java
@@ -0,0 +1,11 @@
+package com.auto.lyric.data;
+
+/**
+ * Created by Runt (qingingrunt2010@qq.com) on 2022/5/2.
+ */
+public class LyricObject {
+ public int begintime; // 开始时间
+ public int endtime; // 结束时间
+ public int timeline; // 单句歌词用时
+ public String lrc; // 单句歌词
+}
diff --git a/app/src/main/java/com/auto/lyric/data/LyricServer.java b/app/src/main/java/com/auto/lyric/data/LyricServer.java
new file mode 100644
index 0000000..8b8ef7e
--- /dev/null
+++ b/app/src/main/java/com/auto/lyric/data/LyricServer.java
@@ -0,0 +1,143 @@
+package com.auto.lyric.data;
+
+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.List;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Created by Runt (qingingrunt2010@qq.com) on 2022/5/4.
+ */
+public class LyricServer {
+
+
+ private static TreeMap<Integer, LyricObject> lrc_map = new TreeMap<>();
+
+ public static TreeMap<Integer, LyricObject> getLrc_map() {
+ return lrc_map;
+ }
+
+
+ /**
+ * 读取歌词文件
+ * @param file 歌词的路径
+ *
+ */
+ public static void read(String file) {
+ TreeMap<Integer, LyricObject> lrc_read =new TreeMap<Integer, LyricObject>();
+ String data = "";
+ try {
+ File saveFile=new File(file);
+ // System.out.println("是否有歌词文件"+saveFile.isFile());
+ if(!saveFile.isFile()){
+ return;
+ }
+ //System.out.println("bllrc==="+blLrc);
+ FileInputStream stream = new FileInputStream(saveFile);// context.openFileInput(file);
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(stream,"GB2312"));
+ while ((data = br.readLine()) != null) {
+ readText(data,lrc_read);
+ }
+ stream.close();
+ } catch (FileNotFoundException e) {
+ } catch (IOException e) {
+ }
+ data ="";
+ initLrc(lrc_read);
+
+ }
+
+ public static void read(List<String> texts){
+ TreeMap<Integer, LyricObject> lrc_read =new TreeMap<Integer, LyricObject>();
+ for(String str : texts){
+ readText(str,lrc_read);
+ }
+ initLrc(lrc_read);
+ }
+
+ private static void readText(String text,TreeMap<Integer, LyricObject> lrc_read){
+ Pattern pattern = Pattern.compile("\\d{2}");
+ // System.out.println("++++++++++++>>"+data);
+ /*text = text.replace("[","");//将前面的替换成后面的
+ text = text.replace("]","@");
+ String splitdata[] = text.split("@");//分隔*/
+ String regex = "(?<=\\])";
+ Pattern compile = Pattern.compile(regex);
+ String[] splitdata = compile.split(text,2);//分隔
+ if(text.endsWith("]") || splitdata.length == 1){
+
+ String str = text;
+ str = str.replace("[","");
+ str = str.replace("]","");
+ str = str.replace(":",".");
+ str = str.replace(".","@");
+ String timedata[] =str.split("@");
+ Matcher matcher = pattern.matcher(timedata[0]);
+ if(timedata.length==3 && matcher.matches()){
+ int m = Integer.parseInt(timedata[0]); //分
+ int s = Integer.parseInt(timedata[1]); //秒
+ int ms = Integer.parseInt(timedata[2]); //毫秒
+ int currTime = (m*60+s)*1000+ms*10;
+ LyricObject item1= new LyricObject();
+ item1.begintime = currTime;
+ item1.lrc = "";
+ lrc_read.put(currTime,item1);
+ }
+ } else{
+ String lrcContenet = splitdata[1];
+ String tmpstr = splitdata[0];
+ tmpstr = tmpstr.replace("[","");
+ tmpstr = tmpstr.replace("]","");
+ tmpstr = tmpstr.replace(":",".");
+ tmpstr = tmpstr.replace(".","@");
+ String timedata[] =tmpstr.split("@");
+ Matcher matcher = pattern.matcher(timedata[0]);
+ if(timedata.length==3 && matcher.matches()){
+ int m = Integer.parseInt(timedata[0]); //分
+ int s = Integer.parseInt(timedata[1]); //秒
+ int ms = Integer.parseInt(timedata[2]); //毫秒
+ int currTime = (m*60+s)*1000+ms*10;
+ LyricObject item1= new LyricObject();
+ item1.begintime = currTime;
+ item1.lrc = lrcContenet;
+ lrc_read.put(currTime,item1);// 将currTime当标签 item1当数据 插入TreeMap里
+ }
+ }
+ }
+
+ /*
+ * 遍历hashmap 计算每句歌词所需要的时间
+ */
+ private static void initLrc(TreeMap<Integer, LyricObject> lrc_read){
+ lrc_map.clear();
+ Iterator<Integer> iterator = lrc_read.keySet().iterator();
+ LyricObject oldval = null;
+ int i =0;
+ for(Integer key : lrc_read.keySet()){
+ LyricObject val = lrc_read.get(key);
+ if (oldval == null) {
+ oldval = val;
+ } else {
+ LyricObject item1= new LyricObject();
+ item1 = oldval;
+ item1.timeline = val.begintime-oldval.begintime;
+ lrc_map.put(new Integer(i), item1);
+ i++;
+ oldval = val;
+ }
+ if (lrc_read.size() > i) {
+ lrc_map.put(new Integer(i), val);
+ }
+ }
+ }
+
+
+}
diff --git a/app/src/main/java/com/auto/lyric/data/SendText.java b/app/src/main/java/com/auto/lyric/data/SendText.java
new file mode 100644
index 0000000..311b12d
--- /dev/null
+++ b/app/src/main/java/com/auto/lyric/data/SendText.java
@@ -0,0 +1,14 @@
+package com.auto.lyric.data;
+
+import java.util.ArrayList;
+
+/**
+ * Created by Runt (qingingrunt2010@qq.com) on 2022/5/1.
+ */
+public class SendText {
+ public ArrayList<String> texts;//文本
+
+ public SendText(ArrayList<String> texts) {
+ this.texts = texts;
+ }
+}
diff --git a/app/src/main/java/com/auto/lyric/data/TextBean.java b/app/src/main/java/com/auto/lyric/data/TextBean.java
new file mode 100644
index 0000000..75a4891
--- /dev/null
+++ b/app/src/main/java/com/auto/lyric/data/TextBean.java
@@ -0,0 +1,14 @@
+package com.auto.lyric.data;
+
+/**
+ * Created by Runt (qingingrunt2010@qq.com) on 2022/5/1.
+ */
+public class TextBean {
+ public TextBean(long waitTime, String text) {
+ this.waitTime = waitTime;
+ this.text = text;
+ }
+
+ public long waitTime;//间隔时间
+ public String text;//文本
+}
diff --git a/app/src/main/java/com/auto/lyric/service/FloatingWindowService.java b/app/src/main/java/com/auto/lyric/service/FloatingWindowService.java
index 720e9e6..426ee8c 100644
--- a/app/src/main/java/com/auto/lyric/service/FloatingWindowService.java
+++ b/app/src/main/java/com/auto/lyric/service/FloatingWindowService.java
@@ -1,6 +1,9 @@
package com.auto.lyric.service;
import android.app.Service;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Build;
@@ -13,14 +16,21 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
+import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.core.view.LayoutInflaterFactory;
import com.auto.lyric.R;
+import com.auto.lyric.data.LyricServer;
import com.auto.lyric.databinding.FloatViewBinding;
import com.auto.lyric.util.DeviceUtil;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Timer;
+import java.util.TimerTask;
/**
* 全局悬浮窗
@@ -31,9 +41,29 @@
private WindowManager manager;
private WindowManager.LayoutParams params;
FloatViewBinding binding;
- Handler handler;
final String TAG = "FloatingWindowService";
+ final int THREAD_STOP = 0, THREAD_START = 1 , KEYBOARD_SEND = 100,UPDATE_TIME = 200;
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+ SimpleDateFormat msFormat = new SimpleDateFormat("mm:ss.SSS");
+ boolean pause;
+ int progress;
+ Handler handler;
+
+ Timer timer;
+ ServiceTask task;
+ class ServiceTask extends TimerTask{
+ @Override
+ public void run() {
+ int index = binding.lyric.getIndex(progress+=10);
+ binding.lyric.setOffsetY(220 - index * (binding.lyric.getSIZEWORD() + 44));
+ binding.lyric.invalidate();
+ handler.sendEmptyMessage(UPDATE_TIME);
+ if(index == LyricServer.getLrc_map().size()-1){
+ handler.sendEmptyMessage(THREAD_STOP);
+ }
+ }
+ };
@Override
public void onCreate() {
super.onCreate();
@@ -47,19 +77,14 @@
}else {
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
+ binding.btnBack.setEnabled(false);
+ binding.btnFast.setEnabled(false);
+ binding.btnPause.setEnabled(false);
params.format = PixelFormat.RGBA_8888;
params.gravity = Gravity.LEFT | Gravity.TOP;
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = DeviceUtil.convertDpToPixel(200,getBaseContext());
- handler = new Handler(this.getMainLooper()){
- @Override
- public void handleMessage(@NonNull Message msg) {
- binding.lyric.setText(msg.obj.toString());
- int offset = binding.lyric.getLineCount() * binding.lyric.getLineHeight();
-
- }
- };
binding.close.setOnClickListener(v ->{
stopService(new Intent(this,this.getClass()));
stopService(new Intent(this,AutoInputService.class));
@@ -75,14 +100,58 @@
|| event.getAction() == MotionEvent.ACTION_UP){
params.y = (int) event.getRawY() - DeviceUtil.getStatusBarHeight(getBaseContext()) - startY;
manager.updateViewLayout(binding.getRoot(), params);
- Log.e(TAG,"ACTION_MOVE V:"+params.y);
+ //Log.e(TAG,"ACTION_MOVE V:"+params.y);
}
- Log.e(TAG,"onTouch event:"+event);
- Log.e(TAG,"onTouch getRawY:"+event.getRawY());
+// Log.e(TAG,"onTouch event:"+event);
+// Log.e(TAG,"onTouch getRawY:"+event.getRawY());
return true;
}
});
+ binding.btnPause.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(pause){
+ pause = false;
+ binding.btnPause.setText("暂停");
+ binding.btnBack.setEnabled(true);
+ binding.btnFast.setEnabled(true);
+ start();
+ }else{
+ pause = true;
+ binding.btnPause.setText("继续");
+ binding.btnBack.setEnabled(false);
+ binding.btnFast.setEnabled(false);
+ timer.cancel();
+ }
+ }
+ });
+ binding.btnFast.setOnClickListener(v -> progress+=700);
+ binding.btnBack.setOnClickListener(v -> progress-=700);
+ binding.btnStart.setOnClickListener(v -> {
+ try {
+ if(new Date().getTime() > dateFormat.parse("2022-09-30 04:00:00").getTime()){
+ Toast.makeText(getApplicationContext(),"软件使用时间已过期", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ if(binding.btnStart.getText().equals("开启")){
+ progress = 0 ;
+ start();
+ startService(new Intent(this,AutoInputService.class));
+ }else{
+ binding.btnStart.setText("开启");
+ binding.btnBack.setEnabled(false);
+ binding.btnFast.setEnabled(false);
+ binding.btnPause.setEnabled(false);
+ progress = 0 ;
+ timer.cancel();
+ stopService(new Intent(this,AutoInputService.class));
+ }
+ });
+ initHandler();
}
@Nullable
@@ -91,10 +160,41 @@
return null;
}
+ private void initHandler(){
+ handler = new Handler(this.getMainLooper()){
+ @Override
+ public void handleMessage(@NonNull Message msg) {
+ super.handleMessage(msg);
+ if(msg.what == THREAD_START){//开始
+ AutoInputService.flag = true;
+ binding.btnPause.performClick();
+ }else if(msg.what == THREAD_STOP){//停止
+ AutoInputService.flag = false;
+ binding.btnStart.performClick();
+
+ }else if(msg.what == KEYBOARD_SEND){//发送文本
+ copy(msg.obj.toString());
+ Intent intent = new Intent();
+ intent.setAction(AutoInputService.class.getName());
+ intent.putExtra("action",AutoInputService.ACTION_PASTE);
+ sendBroadcast(intent);
+ intent.putExtra("action",AutoInputService.ACTION_SEND);
+ sendBroadcast(intent);
+ }else if(msg.what == -1){//显示在输入框中
+
+ //Toast.makeText(getBaseContext(),"上一句--"+msg.obj,Toast.LENGTH_SHORT).show();
+ }else if(msg.what == UPDATE_TIME){
+ binding.timer.setText(msFormat.format(progress));
+ }
+ }
+ };
+ }
+
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG,"onStartCommand flags:"+flags+" startId:"+startId+ " intent:"+intent);
manager.addView(binding.getRoot(),params);
+ binding.lyric.setTextSize();
return super.onStartCommand(intent, flags, startId);
}
@@ -102,7 +202,35 @@
public void onDestroy() {
super.onDestroy();
Log.e(TAG,"onDestroy ");
+ timer.cancel();
manager.removeView(binding.getRoot());
-
}
+
+ /**
+ * 开始
+ */
+ private void start(){
+ timer = new Timer();
+ task = new ServiceTask();
+ timer.schedule(task,0,10);
+ binding.btnStart.setText("停止");
+ binding.btnPause.setText("暂停");
+ binding.btnBack.setEnabled(true);
+ binding.btnFast.setEnabled(true);
+ binding.btnPause.setEnabled(true);
+ }
+
+
+
+ //复制
+ private void copy(String data) {
+ // 获取系统剪贴板
+ ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+ // 创建一个剪贴数据集,包含一个普通文本数据条目(需要复制的数据),其他的还有
+ ClipData clipData = ClipData.newPlainText(null, data);
+ // 把数据集设置(复制)到剪贴板
+ clipboard.setPrimaryClip(clipData);
+ }
+
+
}
diff --git a/app/src/main/java/com/auto/lyric/widgets/LyricView.java b/app/src/main/java/com/auto/lyric/widgets/LyricView.java
index 47c4f82..864d1f2 100644
--- a/app/src/main/java/com/auto/lyric/widgets/LyricView.java
+++ b/app/src/main/java/com/auto/lyric/widgets/LyricView.java
@@ -1,151 +1,209 @@
package com.auto.lyric.widgets;
-import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
-import android.graphics.Typeface;
-import android.media.MediaPlayer;
-import android.os.Bundle;
-import android.os.Handler;
import android.util.AttributeSet;
-import android.widget.TextView;
+import android.util.Log;
+import android.view.MotionEvent;
-import com.auto.lyric.R;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
+import com.auto.lyric.data.LyricObject;
+import com.auto.lyric.data.LyricServer;
+import com.auto.lyric.util.DeviceUtil;
/**
* 歌词
* Created by Runt (qingingrunt2010@qq.com) on 2022/4/30.
*/
public class LyricView extends androidx.appcompat.widget.AppCompatTextView {
- private Paint mPaint;
- private float mX;
- private Paint mPathPaint;
- public int index = 0;
- private List<Sentence> list;
- public float mTouchHistoryY;
- private int mY;
- private float middleY;//
- private static final int DY = 40; //
- public LyricView(Context context) {
+
+
+ private float mX; //屏幕X轴的中点,此值固定,保持歌词在X中间显示
+ private float offsetY; //歌词在Y轴上的偏移量,此值会根据歌词的滚动变小
+ private float touchY; //当触摸歌词View时,保存为当前触点的Y轴坐标
+ 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 attr) {
- super(context, attr);
+
+ public LyricView(Context context, AttributeSet attrs) {
+ super(context, attrs);
init();
}
- public LyricView(Context context, AttributeSet attr, int i) {
- super(context, attr, i);
- init();
- }
- private void init() {
- setFocusable(true);
- if(list==null){
- list=new ArrayList<Sentence>();
- Sentence sen=new Sentence(0," ");
- list.add(0, sen);
- }
- //
- mPaint = new Paint();
- mPaint.setAntiAlias(true);
- mPaint.setTextSize(24);
- mPaint.setColor(Color.BLACK);
- mPaint.setAlpha(80);
- mPaint.setTypeface(Typeface.SERIF);
- //
- mPathPaint = new Paint();
- mPathPaint.setAntiAlias(true);
- mPathPaint.setColor(Color.RED);
- mPathPaint.setTextSize(24);
- mPathPaint.setTypeface(Typeface.SANS_SERIF);
- }
+
+ /* (non-Javadoc)
+ * @see android.view.View#onDraw(android.graphics.Canvas)
+ */
+ @Override
protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- canvas.drawColor(0xEFeffff);
- Paint p = mPaint;
- Paint p2 = mPathPaint;
- p.setTextAlign(Paint.Align.LEFT);
- if (index == -1)
- return;
- p2.setTextAlign(Paint.Align.LEFT);
- //
- canvas.drawText(list.get(index).getName(), mX, middleY, p2);
- float tempY = middleY;
- //
- for (int i = index - 1; i >= 0; i--) {
- tempY = tempY - DY;
- if (tempY < 0) {
- break;
- }
- canvas.drawText(list.get(i).getName(), mX, tempY, p);
- }
- tempY = middleY;
- //
- for (int i = index + 1; i < list.size(); i++) {
- //
- tempY = tempY + DY;
- if (tempY > mY) {
- break;
- }
- canvas.drawText(list.get(i).getName(), mX, tempY, p);
- }
- }
- protected void onSizeChanged(int w, int h, int ow, int oh) {
- super.onSizeChanged(w, h, ow, oh);
- mX = w * 0.3f;
- mY = h;
- middleY = h * 0.5f;
- }
- public long updateIndex(int index) {
- if (index == -1)
- return -1;
- this.index=index;
- return index;
- }
- public List<Sentence> getList() {
- return list;
- }
- public void setList(List<Sentence> list) {
- this.list = list;
- }
- public void updateUI(){
- new Thread(new updateThread()).start();
- }
- class updateThread implements Runnable {
- long time = 300;
- int i=0;
- public void run() {
- while (true) {
- long sleeptime = updateIndex(i);
- time += sleeptime;
- mHandler.post(mUpdateResults);
- if (sleeptime == -1)
- return;
- try {
- Thread.sleep(time);
- i++;
- if(i==getList().size())
- {
- i=0;
- time = 300;
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
+ if(LyricServer.getLrc_map().size() > 0){
+ paintHL.setTextSize(SIZEWORD);
+ paint.setTextSize(SIZEWORD);
+ LyricObject temp= LyricServer.getLrc_map().get(lrcIndex);
+ canvas.drawText(temp.lrc, mX, offsetY+(SIZEWORD+INTERVAL)*lrcIndex, paintHL);
+ // 画当前歌词之前的歌词
+ for(int i=lrcIndex-1;i>=0;i--){
+ temp=LyricServer.getLrc_map().get(i);
+ if(offsetY+(SIZEWORD+INTERVAL)*i<0){
+ break;
}
+ canvas.drawText(temp.lrc, mX, offsetY+(SIZEWORD+INTERVAL)*i, paint);
+ }
+ // 画当前歌词之后的歌词
+ for(int i=lrcIndex+1;i<LyricServer.getLrc_map().size();i++){
+ temp=LyricServer.getLrc_map().get(i);
+ if(offsetY+(SIZEWORD+INTERVAL)*i>600){
+ break;
+ }
+ canvas.drawText(temp.lrc, mX, offsetY+(SIZEWORD+INTERVAL)*i, paint);
}
}
- }
- Handler mHandler = new Handler();
- Runnable mUpdateResults = new Runnable() {
- public void run() {
- invalidate(); //
+ else{
+ paint.setTextSize(25);
+ canvas.drawText("找不到歌词", mX, 310, paint);
}
- };
+ super.onDraw(canvas);
+ }
+
+ /* (non-Javadoc)
+ * @see android.view.View#onTouchEvent(android.view.MotionEvent)
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ // TODO Auto-generated method stub
+ float tt=event.getY();
+ switch(event.getAction()){
+ case MotionEvent.ACTION_DOWN:
+ break;
+ case MotionEvent.ACTION_MOVE:
+ touchY=tt-touchY;
+ offsetY=offsetY+touchY;
+ Log.e("LyricView","offsety:"+offsetY);
+ invalidate();
+ break;
+ case MotionEvent.ACTION_UP:
+ break;
+ }
+ touchY=tt;
+ return true;
+ }
+
+ public void init(){
+ offsetY=320;
+
+ paint=new Paint();
+ paint.setTextAlign(Paint.Align.CENTER);
+ paint.setColor(Color.GREEN);
+ paint.setAntiAlias(true);
+ paint.setDither(true);
+ paint.setAlpha(180);
+
+
+ paintHL=new Paint();
+ paintHL.setTextAlign(Paint.Align.CENTER);
+
+ paintHL.setColor(Color.RED);
+ paintHL.setAntiAlias(true);
+ paintHL.setAlpha(255);
+ }
+
+ /**
+ * 根据歌词里面最长的那句来确定歌词字体的大小
+ */
+ public void setTextSize(){
+ if(LyricServer.getLrc_map().size() == 0){
+ return;
+ }
+ int max=LyricServer.getLrc_map().get(0).lrc.length();
+ for(int i=1;i<LyricServer.getLrc_map().size();i++){
+ LyricObject lrcStrLength=LyricServer.getLrc_map().get(i);
+ if(max<lrcStrLength.lrc.length()){
+ max=lrcStrLength.lrc.length();
+ }
+ }
+ SIZEWORD = DeviceUtil.convertDpToPixel(320/max,getContext());
+
+ }
+
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ mX = w * 0.5f;
+ super.onSizeChanged(w, h, oldw, oldh);
+ }
+
+ /**
+ * 歌词滚动的速度
+ *
+ * @return 返回歌词滚动的速度
+ */
+ public Float SpeedLrc(){
+ float speed=0;
+ if(offsetY+(SIZEWORD+INTERVAL)*lrcIndex>220){
+ speed=((offsetY+(SIZEWORD+INTERVAL)*lrcIndex-220)/20);
+
+ } else if(offsetY+(SIZEWORD+INTERVAL)*lrcIndex < 120){
+ Log.i("speed", "speed is too fast!!!");
+ speed = 0;
+ }
+ // if(speed<0.2){
+ // speed=0.2f;
+ // }
+ return speed;
+ }
+
+ /**
+ * 按当前的歌曲的播放时间,从歌词里面获得那一句
+ * @param time 当前歌曲的播放时间
+ * @return 返回当前歌词的索引值
+ */
+ public int getIndex(int time){
+ int index=0;
+ for(int i=0;i<LyricServer.getLrc_map().size();i++){
+ LyricObject temp=LyricServer.getLrc_map().get(i);
+ if(temp.begintime<time){
+ ++index;
+ }
+ }
+ lrcIndex = index-1;
+ if(lrcIndex<0){
+ lrcIndex=0;
+ }
+ return lrcIndex;
+ }
+
+
+ /**
+ * @return the offsetY
+ */
+ public float getOffsetY() {
+ return offsetY;
+ }
+
+ /**
+ * @param offsetY the offsetY to set
+ */
+ public void setOffsetY(float offsetY) {
+ this.offsetY = offsetY;
+ }
+
+ /**
+ * @return 返回歌词文字的大小
+ */
+ public int getSIZEWORD() {
+ return SIZEWORD;
+ }
+
+ /**
+ * 设置歌词文字的大小
+ * @param sIZEWORD the sIZEWORD to set
+ */
+ public void setSIZEWORD(int sIZEWORD) {
+ SIZEWORD = sIZEWORD;
+ }
}
diff --git a/app/src/main/java/com/auto/lyric/widgets/Sentence.java b/app/src/main/java/com/auto/lyric/widgets/Sentence.java
index f2cdf69..ae137c4 100644
--- a/app/src/main/java/com/auto/lyric/widgets/Sentence.java
+++ b/app/src/main/java/com/auto/lyric/widgets/Sentence.java
@@ -6,19 +6,24 @@
public class Sentence {
private String name;
private int index;
+
public Sentence(int index,String name){
this.name=name;
this.index=index;
}
+
public String getName() {
return name;
}
+
public void setName(String name) {
this.name = name;
}
+
public int getIndex() {
return index;
}
+
public void setIndex(int index) {
this.index = index;
}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index fdf1f7a..5fb776e 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -16,6 +16,7 @@
android:padding="10dp"
android:gravity="left"
android:scrollbars="vertical"
+ android:textCursorDrawable="@null"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
diff --git a/app/src/main/res/layout/float_view.xml b/app/src/main/res/layout/float_view.xml
index df671b9..18f7eee 100644
--- a/app/src/main/res/layout/float_view.xml
+++ b/app/src/main/res/layout/float_view.xml
@@ -64,5 +64,28 @@
android:textColor="@color/black"
app:layout_constraintTop_toBottomOf="@id/lyric"
app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toRightOf="@id/btn_pause"
+ app:layout_constraintRight_toLeftOf="@id/btn_start" />
+
+ <Button
+ android:id="@+id/btn_start"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="开启"
+ android:textColor="@color/black"
+ app:layout_constraintTop_toBottomOf="@id/lyric"
+ app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
+
+ <TextView
+ android:id="@+id/timer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/white"
+ android:text="0.000"
+ android:textSize="15sp"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ android:layout_marginTop="10dp"
+ app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index c80f365..f7a09d4 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -2,12 +2,12 @@
<!-- Base application theme. -->
<style name="Theme.AutoLyric" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
- <item name="colorPrimary">@color/white</item>
- <item name="colorPrimaryVariant">@color/color_gray</item>
- <item name="colorOnPrimary">@color/white</item>
+ <item name="colorPrimary">@color/black</item>
+ <item name="colorPrimaryVariant">@color/gray_normal</item>
+ <item name="colorOnPrimary">@color/gray_pressed</item>
<!-- Secondary brand color. -->
- <item name="colorSecondary">@color/white</item>
- <item name="colorSecondaryVariant">@color/color_gray</item>
+ <item name="colorSecondary">@color/gray_normal</item>
+ <item name="colorSecondaryVariant">@color/gray_pressed</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
--
Gitblit v1.9.1