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