From 3f7664f652552a1090f3a3869436d41530d79c0c Mon Sep 17 00:00:00 2001
From: MUQING <1966944300@qq.com>
Date: Sat, 30 Dec 2023 10:01:18 +0800
Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E5=86=99=E6=AD=8C=E8=AF=8D=E7=BB=84?=
=?UTF-8?q?=E4=BB=B6=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=82=AC=E6=B5=AE=E7=AA=97?=
=?UTF-8?q?=E6=AD=8C=E8=AF=8D=E6=95=88=E6=9E=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/build.gradle | 3 +-
app/src/main/AndroidManifest.xml | 1 +
.../main/java/com/muqingbfq/MediaPlayer.java | 6 +-
.../com/muqingbfq/MyButtonClickReceiver.java | 28 ++
app/src/main/java/com/muqingbfq/api/url.java | 6 +-
app/src/main/java/com/muqingbfq/bfq.java | 17 +-
app/src/main/java/com/muqingbfq/bfqkz.java | 3 +-
.../java/com/muqingbfq/fragment/Media.java | 23 +-
.../java/com/muqingbfq/fragment/search.java | 14 +-
app/src/main/java/com/muqingbfq/home.java | 40 ++
app/src/main/java/com/muqingbfq/main.java | 2 +
.../muqingbfq/mq/FloatingLyricsService.java | 221 +++++++++++
.../mq/NotificationManagerCompat.java | 16 +-
app/src/main/java/com/muqingbfq/sz.java | 3 +-
.../main/java/com/muqingbfq/view/LrcView.java | 352 ++++++++++++++++++
app/src/main/res/drawable/bf.xml | 4 +-
app/src/main/res/drawable/like.xml | 4 +-
app/src/main/res/drawable/syq.xml | 4 +-
app/src/main/res/drawable/xyq.xml | 4 +-
app/src/main/res/drawable/zt.xml | 4 +-
app/src/main/res/layout-land/activity_bfq.xml | 3 +-
app/src/main/res/layout/activity_bfq.xml | 192 +++++-----
app/src/main/res/layout/float_lrcview.xml | 77 ++++
app/src/main/res/layout/view_lrc.xml | 12 +
app/src/main/res/values/attrs.xml | 8 +
25 files changed, 902 insertions(+), 145 deletions(-)
create mode 100644 app/src/main/java/com/muqingbfq/mq/FloatingLyricsService.java
create mode 100644 app/src/main/java/com/muqingbfq/view/LrcView.java
create mode 100644 app/src/main/res/layout/float_lrcview.xml
create mode 100644 app/src/main/res/layout/view_lrc.xml
create mode 100644 app/src/main/res/values/attrs.xml
diff --git a/app/build.gradle b/app/build.gradle
index bcad2c1..729b34c 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -51,7 +51,8 @@ dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'com.github.bumptech.glide:glide:4.16.0'
- implementation 'com.github.wangchenyan:lrcview:2.2.1'
+// 废弃的歌词组件
+// implementation 'com.github.wangchenyan:lrcview:2.2.1'
implementation 'com.google.android.flexbox:flexbox:3.0.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a6e5cc9..5ccfa37 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -72,6 +72,7 @@
+
{
});
- }
+ }*/
}
@SuppressLint("ClickableViewAccessibility")
@Override
@@ -211,7 +209,9 @@ public class bfq extends AppCompatActivity {
public class Touch implements View.OnTouchListener {
- private float downY, moveY;
+ private float downY;
+
+ @SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {LinearLayout root = binding.getRoot();
switch (motionEvent.getAction()) {
@@ -220,7 +220,7 @@ public class bfq extends AppCompatActivity {
break;
case MotionEvent.ACTION_MOVE:
//长按事件,可以移动
- moveY = motionEvent.getRawY();
+ float moveY = motionEvent.getRawY();
//移动的距离
float dy = moveY - downY;
//重新设置控件的位置。移动
@@ -267,6 +267,7 @@ public class bfq extends AppCompatActivity {
public void finish() {
super.finish();
view = null;
- lrcview = null;
+ lrcView = null;
+ main.handler.removeCallbacks(bfqkz.mt.updateSeekBar); // 在播放开始时启动更新进度
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/muqingbfq/bfqkz.java b/app/src/main/java/com/muqingbfq/bfqkz.java
index f343f6f..1fe2122 100644
--- a/app/src/main/java/com/muqingbfq/bfqkz.java
+++ b/app/src/main/java/com/muqingbfq/bfqkz.java
@@ -19,6 +19,7 @@ import androidx.media.MediaBrowserServiceCompat;
import com.muqingbfq.api.url;
import com.muqingbfq.mq.BluetoothMusicController;
+import com.muqingbfq.mq.FloatingLyricsService;
import com.muqingbfq.mq.gj;
import com.muqingbfq.mq.wj;
@@ -95,7 +96,6 @@ public class bfqkz extends MediaBrowserServiceCompat {
playback = new PlaybackStateCompat.Builder()
.setState(PlaybackStateCompat.STATE_NONE, 0, 1.0f)
.build();
-
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(new ComponentName(this, home.class));//用ComponentName得到class对象
@@ -111,6 +111,7 @@ public class bfqkz extends MediaBrowserServiceCompat {
setSessionToken(mSession.getSessionToken());
notify = new com.muqingbfq.mq.NotificationManagerCompat(this);
+
}
class callback extends MediaSessionCompat.Callback {
diff --git a/app/src/main/java/com/muqingbfq/fragment/Media.java b/app/src/main/java/com/muqingbfq/fragment/Media.java
index 2ef6973..7e18a95 100644
--- a/app/src/main/java/com/muqingbfq/fragment/Media.java
+++ b/app/src/main/java/com/muqingbfq/fragment/Media.java
@@ -1,5 +1,7 @@
package com.muqingbfq.fragment;
+
import android.widget.SeekBar;
+
import com.muqingbfq.R;
import com.muqingbfq.bfq;
import com.muqingbfq.bfq_an;
@@ -7,8 +9,11 @@ import com.muqingbfq.bfqkz;
import com.muqingbfq.databinding.ActivityBfqBinding;
import com.muqingbfq.main;
import com.muqingbfq.mq.gj;
+import com.muqingbfq.view.LrcView;
+
import org.json.JSONObject;
-public class Media{
+
+public class Media {
public static void setTime_a(String str) {
if (bfq.view == null) {
return;
@@ -35,7 +40,8 @@ public class Media{
return;
}
bfq.binding.tdt.setProgress(progress);
- bfq.lrcview.updateTime(progress);
+// bfq.lrcview.updateTime(progress);
+ bfq.lrcView.setTimeLrc(progress);
}
public static void setbf(boolean bool) {
@@ -56,11 +62,13 @@ public class Media{
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
setTime_b(bfq_an.getTime(progress));
}
+
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// 拖动条移动中
main.handler.removeCallbacks(bfqkz.mt.updateSeekBar);
}
+
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// 播放音乐到指定位置
@@ -70,12 +78,11 @@ public class Media{
});
//初始化播放器列表
if (bfqkz.xm != null) {
-// main.handler.removeCallbacks(bfqkz.mt.updateSeekBar); // 在播放开始时启动更新进度
long duration = bfqkz.mt.getDuration();
- binding.tdt.setMax((int) bfqkz.mt.getDuration());
+ binding.tdt.setMax(bfqkz.mt.getDuration());
setTime_a(bfq_an.getTime(duration));
long position = bfqkz.mt.getCurrentPosition();
-// main.handler.post(bfqkz.mt.updateSeekBar); // 在播放开始时启动更新进度
+ main.handler.post(bfqkz.mt.updateSeekBar); // 在播放开始时启动更新进度
loadLyric();
setProgress((int) position);
}
@@ -83,7 +90,7 @@ public class Media{
public static void loadLyric() {
- if (bfq.lrcview == null || com.muqingbfq.bfq.lrc == null) {
+ if (com.muqingbfq.bfq.lrc == null) {
return;
}
JSONObject jsonObject;
@@ -95,7 +102,9 @@ public class Media{
} catch (Exception e) {
gj.sc(e);
}
- bfq.lrcview.loadLrc(a, b);
+ LrcView.setLrc(a, b);
+// bfq.lrcView.getLrc();
+// bfq.lrcView.loadLrc(a, b);
}
diff --git a/app/src/main/java/com/muqingbfq/fragment/search.java b/app/src/main/java/com/muqingbfq/fragment/search.java
index 65a1826..965770a 100644
--- a/app/src/main/java/com/muqingbfq/fragment/search.java
+++ b/app/src/main/java/com/muqingbfq/fragment/search.java
@@ -25,7 +25,6 @@ import com.muqingbfq.databinding.FragmentSearchBinding;
import com.muqingbfq.list.MyViewHoder;
import com.muqingbfq.main;
import com.muqingbfq.mq.gj;
-import com.muqingbfq.mq.wj;
import com.muqingbfq.mq.wl;
import com.muqingbfq.xm;
@@ -39,7 +38,6 @@ public class search extends Fragment {
public static RecyclerView.Adapter lbspq;
List list = new ArrayList<>();
List xmList = new ArrayList<>();
- gd.baseadapter adapter_gd;
public String name;
public FragmentSearchBinding inflate;
@@ -55,7 +53,6 @@ public class search extends Fragment {
TypedValue typedValue = new TypedValue();
requireContext().getTheme().resolveAttribute(android.R.attr.windowBackground, typedValue, true);
// 设置背景颜色
- adapter_gd = new gd.baseadapter(getContext(), xmList);
view.setBackgroundColor(typedValue.data);
inflate.tablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
@@ -101,7 +98,7 @@ public class search extends Fragment {
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(),
k);
inflate.recyclerview.setLayoutManager(gridLayoutManager);
- inflate.recyclerview.setAdapter(adapter_gd);
+ inflate.recyclerview.setAdapter(new gd.baseadapter(getContext(), xmList));
}
new start(name);
}
@@ -123,14 +120,7 @@ public class search extends Fragment {
} else if (i == 1) {
gd();
}
- main.handler.post(() -> {
- if (i == 0) {
- lbspq.notifyDataSetChanged();
- } else if (i == 1) {
- adapter_gd.notifyDataSetChanged();
- }
-// lbspq.notifyDataSetChanged();
- });
+ main.handler.post(() -> inflate.recyclerview.getAdapter().notifyDataSetChanged());
}
}
diff --git a/app/src/main/java/com/muqingbfq/home.java b/app/src/main/java/com/muqingbfq/home.java
index a839c83..c310cef 100644
--- a/app/src/main/java/com/muqingbfq/home.java
+++ b/app/src/main/java/com/muqingbfq/home.java
@@ -5,12 +5,16 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.net.Uri;
import android.os.Bundle;
+import android.provider.Settings;
import android.support.v4.media.MediaBrowserCompat;
import android.util.DisplayMetrics;
import android.view.Menu;
import android.view.MenuItem;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
@@ -21,9 +25,11 @@ import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.muqingbfq.databinding.ActivityHomeBinding;
+import com.muqingbfq.databinding.FloatLrcviewBinding;
import com.muqingbfq.fragment.bfq_db;
import com.muqingbfq.fragment.gd_adapter;
import com.muqingbfq.fragment.wode;
+import com.muqingbfq.mq.FloatingLyricsService;
import com.muqingbfq.mq.gj;
import java.util.ArrayList;
@@ -77,6 +83,7 @@ public class home extends AppCompatActivity {
binding.editView.setOnClickListener(view ->
startActivity(new Intent(this, activity_search.class)));
UI();
+// startService(new Intent(this, FloatingLyricsService.class));
} catch (Exception e) {
yc.tc(this, e);
}
@@ -87,21 +94,25 @@ public class home extends AppCompatActivity {
private class Adaper extends FragmentStateAdapter {
List list = new ArrayList<>();
+
public Adaper(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
list.add(new gd_adapter());
list.add(new wode());
}
+
@NonNull
@Override
public Fragment createFragment(int position) {
return list.get(position);
}
+
@Override
public int getItemCount() {
return list.size();
}
}
+
public void UI() {
adapter = new Adaper(this);
binding.viewPager.setAdapter(adapter);
@@ -144,6 +155,35 @@ public class home extends AppCompatActivity {
});
}
+ @Override
+ protected void onStart() {
+ super.onStart();
+ stopService(new Intent(this, FloatingLyricsService.class));
+ }
+
+ ActivityResultLauncher LyricsService =
+ registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
+ if (Settings.canDrawOverlays(this)) {
+ startService(new Intent(this, FloatingLyricsService.class));
+ }
+ });
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ if (!FloatingLyricsService.get()) {
+ return;
+ }
+ if (!Settings.canDrawOverlays(this)) {
+ // 无权限,需要申请权限
+ Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
+ Uri.parse("package:" + getPackageName()));
+ LyricsService.launch(intent);
+ } else {
+ startService(new Intent(this, FloatingLyricsService.class));
+ }
+ }
+
@Override
protected void onPause() {
super.onPause();
diff --git a/app/src/main/java/com/muqingbfq/main.java b/app/src/main/java/com/muqingbfq/main.java
index 3b58d8e..6a56926 100644
--- a/app/src/main/java/com/muqingbfq/main.java
+++ b/app/src/main/java/com/muqingbfq/main.java
@@ -2,6 +2,7 @@ package com.muqingbfq;
import android.annotation.SuppressLint;
import android.app.Application;
+import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;
@@ -9,6 +10,7 @@ import android.os.Looper;
import androidx.appcompat.app.AppCompatDelegate;
import com.muqingbfq.login.visitor;
+import com.muqingbfq.mq.FloatingLyricsService;
import com.muqingbfq.mq.wj;
import com.muqingbfq.mq.wl;
diff --git a/app/src/main/java/com/muqingbfq/mq/FloatingLyricsService.java b/app/src/main/java/com/muqingbfq/mq/FloatingLyricsService.java
new file mode 100644
index 0000000..2c28e15
--- /dev/null
+++ b/app/src/main/java/com/muqingbfq/mq/FloatingLyricsService.java
@@ -0,0 +1,221 @@
+package com.muqingbfq.mq;
+
+import android.annotation.SuppressLint;
+import android.app.Service;
+import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.os.Build;
+import android.os.Handler;
+import android.os.IBinder;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+
+import androidx.annotation.Nullable;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.muqingbfq.bfq_an;
+import com.muqingbfq.bfqkz;
+import com.muqingbfq.databinding.FloatLrcviewBinding;
+import com.muqingbfq.main;
+import com.muqingbfq.view.LrcView;
+
+import java.io.File;
+import java.lang.reflect.Type;
+
+public class FloatingLyricsService extends Service implements View.OnClickListener, View.OnTouchListener {
+ private WindowManager windowManager;
+ private View layout;
+ public Runnable updateSeekBar = new Runnable() {
+ @Override
+ public void run() {
+ if (bfqkz.mt.isPlaying() && lrcView != null) {
+ long position = bfqkz.mt.getCurrentPosition();
+ lrcView.setTimeLrc(position);
+ }
+ handler.postDelayed(this, 1000); // 每秒更新一次进度
+ }
+ };
+ @SuppressLint("StaticFieldLeak")
+ public static FloatingLyricsService lei;
+
+ public static boolean get() {
+ File file = new File(wj.filesdri + "FloatingLyricsService.json");
+ if (file.exists() && file.isFile()) {
+ String dqwb = wj.dqwb(file.toString());
+ Gson gson = new Gson();
+ Type type = new TypeToken() {
+ }.getType();
+ SETUP setup = gson.fromJson(dqwb, type);
+ return setup.i != 0;
+ } else {
+ return true;
+ }
+ }
+ Handler handler = new Handler();
+ LrcView lrcView;
+ WindowManager.LayoutParams params;
+
+ public static class SETUP {
+ //0是关闭 1是打开 2是锁定
+ public int i;
+ public float TOP;
+ public int Y;
+ }
+
+ public SETUP setup = new SETUP();
+ File file;
+
+ public int lock() {
+ if (setup != null && setup.i == 2) {
+ return WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ }
+ return WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ lei = this;
+ try {
+ file = new File(wj.filesdri + "FloatingLyricsService.json");
+ if (file.exists() && file.isFile()) {
+ String dqwb = wj.dqwb(file.toString());
+ Gson gson = new Gson();
+ Type type = new TypeToken() {
+ }.getType();
+ setup = gson.fromJson(dqwb, type);
+ } else {
+ setup.i = 1;
+ setup.TOP = 0;
+ setup.Y = -main.g;
+ }
+
+
+ } catch (Exception e) {
+ wj.sc(file.toString());
+ gj.sc(e);
+ }
+ // 创建悬浮窗歌词的 View
+// FloatLrcviewBinding
+ FloatLrcviewBinding binding = FloatLrcviewBinding.inflate(LayoutInflater.from(this));
+ layout = binding.getRoot();
+ layout.setOnTouchListener(this);
+// ViewGroup.LayoutParams layoutParams = layout.getLayoutParams();
+// layout.setLayoutParams(layoutParams);
+
+// int i = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;FLAG_NOT_TOUCH_MODAL
+ params = new WindowManager.LayoutParams(
+ WindowManager.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.WRAP_CONTENT,
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
+ WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
+ WindowManager.LayoutParams.TYPE_PHONE,
+ lock(),
+ PixelFormat.TRANSLUCENT
+ );
+
+ params.y = setup.Y;
+
+ lrcView = binding.lrcView;
+ bfq_an.kz bfqAn = new bfq_an.kz();
+ binding.kg.setOnClickListener(bfqAn);
+ binding.syq.setOnClickListener(bfqAn);
+ binding.xyq.setOnClickListener(bfqAn);
+ binding.lock.setOnClickListener(this);
+// params.gravity = Gravity.CENTER;
+
+
+ // 获取 WindowManager 并将悬浮窗歌词添加到窗口中
+ windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
+ if (setup.i == 2) {
+ params.flags = lock();
+ layout.setBackground(null);
+ lrcView.setAlpha(0.5f);
+ layout.findViewById(com.muqingbfq.R.id.controlLayout).setVisibility(View.GONE);
+ }
+ windowManager.addView(layout, params);
+ gj.sc("添加成功");
+ handler.post(updateSeekBar); // 在播放开始时启动更新进度
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ // 在 Service 销毁时移除悬浮窗歌词
+ if (windowManager != null && layout != null) {
+ windowManager.removeView(layout);
+ handler.removeCallbacks(bfqkz.mt.updateSeekBar); // 在播放开始时启动更新进度
+ }
+ lei = null;
+ }
+
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ public void baocun() {
+ String s = new Gson().toJson(setup);
+ wj.xrwb(new File(wj.filesdri + "FloatingLyricsService.json").toString(), s);
+ }
+
+ private int initialY;
+ private float initialTouchY;
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ switch (motionEvent.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ // 记录触摸事件的初始位置和坐标
+ initialY = params.y;
+ initialTouchY = motionEvent.getRawY();
+ return true;
+ case MotionEvent.ACTION_MOVE:
+ // 计算触摸事件的偏移量,将悬浮窗口的位置设置为初始位置加上偏移量
+ int offsetY = (int) (motionEvent.getRawY() - initialTouchY);
+ setup.Y = initialY + offsetY;
+ params.y = setup.Y;
+ windowManager.updateViewLayout(layout, params);
+ return true;
+ case MotionEvent.ACTION_UP:
+ baocun();
+ break;
+
+ }
+ return false;
+ }
+
+ @Override
+ public void onClick(View view) {
+ setyc();
+ }
+
+ public void setyc() {
+ setup.i = 2;
+ params.flags = lock();
+ layout.setBackground(null);
+ lrcView.setAlpha(0.5f);
+ layout.findViewById(com.muqingbfq.R.id.controlLayout).setVisibility(View.GONE);
+ windowManager.updateViewLayout(layout, params);
+ baocun();
+ }
+
+ public void show() {
+ setup.i = 1;
+ params.flags = lock();
+ layout.setBackgroundColor(Color.parseColor("#50000000"));
+ lrcView.setAlpha(1.0f);
+ layout.findViewById(com.muqingbfq.R.id.controlLayout).setVisibility(View.VISIBLE);
+ windowManager.updateViewLayout(layout, params);
+ baocun();
+ }
+}
diff --git a/app/src/main/java/com/muqingbfq/mq/NotificationManagerCompat.java b/app/src/main/java/com/muqingbfq/mq/NotificationManagerCompat.java
index 3efd72d..d0e3246 100644
--- a/app/src/main/java/com/muqingbfq/mq/NotificationManagerCompat.java
+++ b/app/src/main/java/com/muqingbfq/mq/NotificationManagerCompat.java
@@ -54,8 +54,10 @@ public class NotificationManagerCompat {
setAction("syq"));
pendingIntent_xyq = getBroadcast(context, my.
setAction("xyq"));
+ pendingIntent_lrc = getBroadcast(context, my.
+ setAction("lrc"));
style = new androidx.media.app.NotificationCompat.MediaStyle()
- .setShowActionsInCompactView(0, 1, 2)
+ .setShowActionsInCompactView(1, 2, 3)
.setMediaSession(bfqkz.mSession.getSessionToken());
notificationManager = androidx.core.app.NotificationManagerCompat.from(context);
notificationBuilder = getNotificationBuilder(context)
@@ -79,10 +81,13 @@ public class NotificationManagerCompat {
zz = bfqkz.xm.zz;
}
notificationBuilder.mActions.clear();
- notificationBuilder.addAction(android.R.drawable.ic_media_previous, "syq", pendingIntent_syq) // #0
- .addAction(bfqkz.mt.isPlaying() ? android.R.drawable.ic_media_pause : android.R.drawable.ic_media_play
+ notificationBuilder
+ .addAction(R.drawable.like, "like", pendingIntent_kg) // #0
+ .addAction(R.drawable.syq, "syq", pendingIntent_syq) // #0
+ .addAction(bfqkz.mt.isPlaying() ? R.drawable.bf : R.drawable.zt
, "kg", pendingIntent_kg) // #1
- .addAction(android.R.drawable.ic_media_next, "xyq", pendingIntent_xyq)
+ .addAction(R.drawable.xyq, "xyq", pendingIntent_xyq)
+ .addAction(R.drawable.lock, "lrc", pendingIntent_lrc)
.setContentTitle(name)
.setContentText(zz)
.setOngoing(bfqkz.mt.isPlaying());
@@ -91,7 +96,8 @@ public class NotificationManagerCompat {
private PendingIntent pendingIntent_kg,
pendingIntent_syq,
- pendingIntent_xyq;
+ pendingIntent_xyq,
+ pendingIntent_lrc;
private final String CHANNEL_ID = "muqing_yy_id";
public void notificationManager_notify() {
diff --git a/app/src/main/java/com/muqingbfq/sz.java b/app/src/main/java/com/muqingbfq/sz.java
index bec6aad..a0ba1c8 100644
--- a/app/src/main/java/com/muqingbfq/sz.java
+++ b/app/src/main/java/com/muqingbfq/sz.java
@@ -79,7 +79,8 @@ public class sz extends AppCompatActivity {
return super.onOptionsItemSelected(item);
}
- ActivityResultLauncher intent = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
+ ActivityResultLauncher intent = registerForActivityResult(
+ new ActivityResultContracts.StartActivityForResult(),
result -> {
if (Settings.canDrawOverlays(this)) {
com.muqingbfq.mq.floating.start(sz.this);
diff --git a/app/src/main/java/com/muqingbfq/view/LrcView.java b/app/src/main/java/com/muqingbfq/view/LrcView.java
new file mode 100644
index 0000000..4543759
--- /dev/null
+++ b/app/src/main/java/com/muqingbfq/view/LrcView.java
@@ -0,0 +1,352 @@
+package com.muqingbfq.view;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.text.Layout;
+import android.text.StaticLayout;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.LinearSmoothScroller;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.muqingbfq.R;
+import com.muqingbfq.main;
+import com.muqingbfq.mq.gj;
+import com.muqingbfq.yc;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LrcView extends RecyclerView {
+ private void sc(Object obj) {
+ gj.sc("LRC " + obj);
+ }
+
+ static List lrclist = new ArrayList<>();
+
+ static class lrc {
+ String lrc, tlyric;
+ long time;
+
+ public lrc(String lrc, long time) {
+ this.lrc = lrc;
+ this.time = time;
+ }
+
+ public lrc(String lrc, String tlyric, long time) {
+ this.lrc = lrc;
+ this.tlyric = tlyric;
+ this.time = time;
+ }
+
+ public lrc setTlyric(String str) {
+ this.tlyric = str;
+ return this;
+ }
+
+ }
+
+ public LrcView(Context context) {
+ super(context);
+ init();
+ }
+
+ AttributeSet attrs;
+ boolean Lrcline;
+ LinearLayoutManager linearLayoutManager;
+
+ public LrcView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ this.attrs = attrs;
+ init();
+ }
+
+ public LrcView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ this.attrs = attrs;
+ init();
+ }
+
+ private void init() {
+ if (attrs != null) {
+ TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.LrcView);
+ TextColor = ta.getColor(R.styleable.LrcView_TextColor,
+ ContextCompat.getColor(getContext(), R.color.text));
+ Lrcline = ta.getBoolean(R.styleable.LrcView_Lrcline, true);
+ ta.recycle();
+ }
+ linearLayoutManager = new LinearLayoutManager(getContext()) {
+
+ @Override
+ public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
+ RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());
+ smoothScroller.setTargetPosition(position);
+ startSmoothScroll(smoothScroller);
+ }
+
+ };
+ setLayoutManager(linearLayoutManager);
+ setAdapter(new adaper());
+ setForeground(null);
+ setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER);
+ if (!Lrcline) {
+ addItemDecoration( new RecyclerView.ItemDecoration() {
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ super.getItemOffsets(outRect, view, parent, state);
+
+ int parentHeight = parent.getHeight();
+ int childHeight = view.getHeight();
+
+ int topMargin = (parentHeight - childHeight) / 2;
+
+ // 设置第一项的顶部间距
+ if (parent.getChildAdapterPosition(view) == 0) {
+ outRect.top = topMargin;
+ }
+ }
+ });
+ }
+ }
+
+ private static class CenterSmoothScroller extends LinearSmoothScroller {
+
+ CenterSmoothScroller(Context context) {
+ super(context);
+ }
+
+ @Override
+ public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
+ return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
+ }
+
+ @Override
+ protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
+ return 100f / displayMetrics.densityDpi;
+ }
+ }
+
+ public static void setLrc(String a, String b) {
+ setLrc(a);
+ if (TextUtils.isEmpty(b)) {
+ return;
+ }
+ b.trim();
+ String[] lines = b.split("\n");
+ for (String line : lines) {
+ String[] parts = line.split("]");
+ if (parts.length >= 2) {
+ String timeString = parts[0].substring(1);
+ String lyric = parts[1].trim();
+ String[] timeParts = timeString.split(":");
+ if (timeParts.length >= 2) {
+ int minute = Integer.parseInt(timeParts[0]);
+ String[] secondParts = timeParts[1].split("\\.");
+ if (secondParts.length >= 2) {
+ int second = Integer.parseInt(secondParts[0]);
+ int millisecond = Integer.parseInt(secondParts[1]);
+ long time = (long) minute * 60 * 1000 + second * 1000L + millisecond;
+ int currentLineIndex = getCurrentLineIndex(time);
+ lrclist.set(currentLineIndex, lrclist.get(currentLineIndex).setTlyric(lyric));
+// gj.sc(lyric);
+ }
+ }
+ }
+ }
+ }
+
+ public static void setLrc(String a) {
+ lrclist.clear();
+ // 去除空格
+ a.trim();
+ if (TextUtils.isEmpty(a)) {
+ return;
+ }
+ String[] lines = a.split("\n");
+ for (String line : lines) {
+ String[] parts = line.split("]");
+ if (parts.length >= 2) {
+ String timeString = parts[0].substring(1);
+ String lyric = parts[1].trim();
+ String[] timeParts = timeString.split(":");
+ if (timeParts.length >= 2) {
+ int minute = Integer.parseInt(timeParts[0]);
+ String[] secondParts = timeParts[1].split("\\.");
+ if (secondParts.length >= 2) {
+ int second = Integer.parseInt(secondParts[0]);
+ int millisecond = Integer.parseInt(secondParts[1]);
+ long time = (long) minute * 60 * 1000 + second * 1000L + millisecond;
+ lrclist.add(new lrc(lyric, time));
+// gj.sc(lyric);
+ }
+ }
+ }
+ }
+ }
+
+ class adaper extends RecyclerView.Adapter {
+
+ @NonNull
+ @Override
+ public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View inflate = LayoutInflater.from(getContext()).inflate(R.layout.view_lrc, parent, false);
+ TextView textView = inflate.findViewById(R.id.text);
+ textView.setTextColor(TextColor);
+ textView.setTextSize(
+ TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 20,
+ getResources().getDisplayMetrics()));
+ return new VH(inflate);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull VH holder, int position) {
+ if (lrclist.isEmpty()) {
+ holder.textView.setText("纯音乐,请欣赏");
+ return;
+ }
+ if (Lrcline) {
+ int currentLineIndex = getCurrentLineIndex();
+ if (currentLineIndex >= 0 && currentLineIndex < lrclist.size()) {
+
+ String text;
+ if (lrclist.size() <= 3) {
+ for (lrc a : lrclist) {
+ if (a.time == 5940000 && a.lrc.equals("纯音乐,请欣赏")) {
+ text = "纯音乐,请欣赏";
+ holder.textView.setText(text);
+ return;
+ }
+ }
+ }
+ lrc currentLrc = lrclist.get(currentLineIndex);
+ text = currentLrc.lrc;
+ if (currentLrc.tlyric != null) {
+ text += "\n" + currentLrc.tlyric;
+ }
+ holder.textView.setText(text);
+ }
+ } else {
+ try {
+ lrc lrc = lrclist.get(position);
+ StringBuilder stringBuffer = new StringBuilder();
+ stringBuffer.append(lrc.lrc);
+ if (lrc.tlyric != null) {
+ stringBuffer.append("\n").append(lrc.tlyric);
+ }
+ stringBuffer.append("\n");
+ holder.textView.setAlpha(0.1f);
+ if (getCurrentLineIndex(time) == position) {
+ holder.textView.setAlpha(1.0f);
+ }
+ holder.textView.setText(stringBuffer.toString());
+ } catch (Exception e) {
+ gj.sc("LrcView.ADAPER.onBindViewHolder" + e);
+ }
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ gj.sc(lrclist.size());
+ if (lrclist.size() < 3) {
+ for (lrc a : lrclist) {
+ if (a.time == 5940000 && a.lrc.equals("纯音乐,请欣赏")) {
+ return 1;
+ }
+ }
+ }
+ if (Lrcline) {
+ return 1;
+ }
+ if (lrclist.isEmpty()) {
+ return 1;
+ }
+ return lrclist.size();
+ }
+ }
+
+ class VH extends RecyclerView.ViewHolder {
+ TextView textView;
+
+ public VH(@NonNull View itemView) {
+ super(itemView);
+ textView = itemView.findViewById(R.id.text);
+ }
+ }
+/* @Override
+ public void onDraw(@NonNull Canvas canvas) {
+ super.onDraw(canvas);
+ setTimeLrc(canvas);
+ }*/
+
+ private int getCurrentLineIndex() {
+ int index = -1;
+ for (int i = 0; i < lrclist.size(); i++) {
+ lrc lineLrc = lrclist.get(i);
+ if (lineLrc.time <= time) {
+ index = i;
+ } else {
+ break;
+ }
+ }
+ return index;
+ }
+
+ private static int getCurrentLineIndex(long time) {
+ int index = -1;
+ for (int i = 0; i < lrclist.size(); i++) {
+ lrc lineLrc = lrclist.get(i);
+ if (lineLrc.time <= time) {
+ index = i;
+ } else {
+ break;
+ }
+ }
+ return index;
+ }
+
+ int TextColor;
+ long time;
+
+ @SuppressLint("NotifyDataSetChanged")
+ public void setTimeLrc(long a) {
+ this.time = a;
+ if (!Lrcline) {
+ int currentLineIndex = getCurrentLineIndex(a);
+ if (currentLineIndex == -1) {
+ return;
+ }
+ linearLayoutManager.smoothScrollToPosition(this,
+ new RecyclerView.State(), currentLineIndex);
+// smoothScrollToPosition(getCurrentLineIndex(a));
+ getAdapter().notifyItemChanged(--currentLineIndex);
+ getAdapter().notifyItemChanged(getCurrentLineIndex(a));
+ return;
+ }
+ getAdapter().notifyDataSetChanged();
+ }
+
+ public void getLrc() {
+ for (lrc a : lrclist) {
+ sc(a.time + ":" + a.lrc + ":" + a.tlyric);
+ }
+ }
+}
diff --git a/app/src/main/res/drawable/bf.xml b/app/src/main/res/drawable/bf.xml
index 53eafb3..39a973e 100644
--- a/app/src/main/res/drawable/bf.xml
+++ b/app/src/main/res/drawable/bf.xml
@@ -1,6 +1,6 @@
-
-
-
-
+
-
+ android:layout_height="260dp"
+ android:layout_weight="2"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app:layout_constraintBottom_toTopOf="@+id/kg"
+ tools:layout_editor_absoluteX="20dp">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/float_lrcview.xml b/app/src/main/res/layout/float_lrcview.xml
new file mode 100644
index 0000000..78b7cff
--- /dev/null
+++ b/app/src/main/res/layout/float_lrcview.xml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/view_lrc.xml b/app/src/main/res/layout/view_lrc.xml
new file mode 100644
index 0000000..89df9da
--- /dev/null
+++ b/app/src/main/res/layout/view_lrc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..8c64a99
--- /dev/null
+++ b/app/src/main/res/values/attrs.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file