修复BUG,更新UI

This commit is contained in:
muqing 2024-02-21 18:20:05 +08:00
parent 3d8b8e05d3
commit 98a4bd87ad
61 changed files with 708 additions and 1864 deletions

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="C:\Users\19669\.android\avd\Pixel_2_API_30.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-02-17T09:31:32.068883900Z" />
</component>
</project>

View File

@ -12,7 +12,6 @@
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/StatusBarUtil" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/lrcview" />
</set>
</option>
<option name="resolveExternalAnnotations" value="false" />

View File

@ -15,6 +15,8 @@
<option name="callCheckString" value="java.io.InputStream,read|skip|available|markSupported,java.io.Reader,read|skip|ready|markSupported,java.lang.AbstractStringBuilder,capacity|codePointAt|codePointBefore|codePointCount|indexOf|lastIndexOf|offsetByCodePoints|substring|subSequence,java.lang.Boolean,.*,java.lang.Byte,.*,java.lang.Character,.*,java.lang.Double,.*,java.lang.Float,.*,java.lang.Integer,.*,java.lang.Long,.*,java.lang.Math,.*,java.lang.Object,equals|hashCode|toString,java.lang.Short,.*,java.lang.StrictMath,.*,java.lang.String,.*,java.lang.Thread,interrupted,java.math.BigDecimal,.*,java.math.BigInteger,.*,java.net.InetAddress,.*,java.net.URI,.*,java.nio.channels.AsynchronousChannelGroup,.*,java.nio.channels.Channel,isOpen,java.nio.channels.FileChannel,open|map|lock|tryLock|write,java.nio.channels.ScatteringByteChannel,read,java.nio.channels.SocketChannel,open|socket|isConnected|isConnectionPending,java.util.Arrays,.*,java.util.Collections,(?!addAll).*,java.util.List,of,java.util.Map,of|ofEntries|entry,java.util.Set,of,java.util.UUID,.*,java.util.concurrent.BlockingQueue,offer|remove,java.util.concurrent.CountDownLatch,await|getCount,java.util.concurrent.ExecutorService,awaitTermination|isShutdown|isTerminated,java.util.concurrent.ForkJoinPool,awaitQuiescence,java.util.concurrent.Semaphore,tryAcquire|availablePermits|isFair|hasQueuedThreads|getQueueLength|getQueuedThreads,java.util.concurrent.locks.Condition,await|awaitNanos|awaitUntil,java.util.concurrent.locks.Lock,tryLock|newCondition,java.util.regex.Matcher,pattern|toMatchResult|start|end|group|groupCount|matches|find|lookingAt|quoteReplacement|replaceAll|replaceFirst|regionStart|regionEnd|hasTransparentBounds|hasAnchoringBounds|hitEnd|requireEnd,java.util.regex.Pattern,.*,java.util.stream.BaseStream,.*,java.util.stream.DoubleStream,.*,java.util.stream.IntStream,.*,java.util.stream.LongStream,.*,java.util.stream.Stream,.*" />
</inspection_tool>
<inspection_tool class="InnerClassMayBeStatic" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PrivatePropertyName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PropertyName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />

6
.idea/kotlinc.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.8.0" />
</component>
</project>

View File

@ -46,4 +46,7 @@
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK" />
<component name="SuppressKotlinCodeStyleNotification">
<option name="disableForAll" value="true" />
</component>
</project>

View File

@ -29,7 +29,7 @@
* 在使用中有任何问题,欢迎反馈给我,可以用以下联系方式跟我交流
* [邮件](<a target="_blank" href="http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=MAEJBgYJBAQDAABwQUEeU19d" style="text-decoration:none;"><img src="http://rescdn.qqmail.com/zh_CN/htmledition/images/function/qm_open/ico_mailme_12.png"/></a>)
* [邮件](<a target="_blank"%2href="http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=MAEJBgYJBAQDAABwQUEeU19d" style="text-decoration:none;"><img src="http://rescdn.qqmail.com/zh_CN/htmledition/images/function/qm_open/ico_mailme_12.png"/></a>)
* QQ:1966944300
* 后台源码-Github: [网易云音乐 API](https://github.com/Binaryify/NeteaseCloudMusicApi)

View File

@ -1,5 +1,6 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
signingConfigs {
@ -18,8 +19,7 @@ android {
//noinspection ExpiredTargetSdkVersion,OldTargetApi
targetSdk 31
versionCode 1
versionName "1.9.9"
versionName "2.0.0"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
@ -39,11 +39,15 @@ android {
outputFileName = "Cloud_music-${variant.name}-v${variant.versionName}.apk"
}
}
kotlinOptions {
jvmTarget = '1.8'
}
viewBinding {
enabled = true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
@ -54,6 +58,7 @@ dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
//
implementation 'com.github.bumptech.glide:glide:4.16.0'
implementation "androidx.palette:palette:1.0.0"
//
// implementation 'com.github.wangchenyan:lrcview:2.2.1'
@ -65,6 +70,9 @@ dependencies {
implementation 'com.mpatric:mp3agic:0.9.1'
//
api project(path: ':StatusBarUtil')
api project(path: ':lrcview')
implementation project(path: ':StatusBarUtil')
// api project(path: ':lrcview')
//
api "com.github.cy745:EaseView:e11c3208a9"
api "androidx.dynamicanimation:dynamicanimation-ktx:1.0.0-alpha03"
}

View File

@ -24,7 +24,6 @@ import java.io.IOException;
public class MediaPlayer extends android.media.MediaPlayer {
// 每秒更新一次进度
@SuppressLint("UnsafeOptInUsageError")
public MediaPlayer() {
setOnErrorListener((mediaPlayer, i, i1) -> {
@ -88,8 +87,11 @@ public class MediaPlayer extends android.media.MediaPlayer {
bfqkz.xm = mp3;
main.handler.post(() -> {
bfui();
if (bfqkz.notify != null) {
bfqkz.notify.tzl();
}
});
new Thread() {
@Override
public void run() {

View File

@ -14,13 +14,13 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
@ -30,6 +30,7 @@ import com.google.android.flexbox.FlexDirection;
import com.google.android.flexbox.FlexWrap;
import com.google.android.flexbox.FlexboxLayoutManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.search.SearchView;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.muqingbfq.databinding.ActivitySearchBinding;
@ -37,7 +38,6 @@ import com.muqingbfq.fragment.search;
import com.muqingbfq.mq.FragmentActivity;
import com.muqingbfq.mq.gj;
import com.muqingbfq.mq.wj;
import com.muqingbfq.mq.wl;
import com.muqingbfq.view.Edit;
import org.json.JSONArray;
@ -55,14 +55,20 @@ public class activity_search extends FragmentActivity<ActivitySearchBinding> {
public static void start(Activity context, View view) {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(context,
view, "view");
view, "edit");
context.startActivity(new Intent(context, activity_search.class), options.toBundle());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getViewBinding().getRoot());
FlexboxLayoutManager manager = new FlexboxLayoutManager(this);
setToolbar();
FlexboxLayoutManager manager = new FlexboxLayoutManager(this){
@Override
public boolean canScrollVertically() {
return false;
}
};
//设置主轴排列方式
manager.setFlexDirection(FlexDirection.ROW);
//设置是否换行
@ -70,16 +76,6 @@ public class activity_search extends FragmentActivity<ActivitySearchBinding> {
manager.setAlignItems(AlignItems.STRETCH);
binding.listRecycler.setLayoutManager(manager);
binding.listRecycler.setAdapter(new SearchRecordAdapter());
binding.editview.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
String str = v.getText().toString();
if (!str.equals("")) {
start(str);
}
}
return false;
});
binding.deleat.setOnClickListener(v -> new MaterialAlertDialogBuilder(
activity_search.this)
.setTitle("删除")
@ -109,20 +105,17 @@ public class activity_search extends FragmentActivity<ActivitySearchBinding> {
if (null != v) {
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
binding.editview.setText(list.get(i));//把选择的选项内容展示在EditText上
binding.toolbar.setText(list.get(i));//把选择的选项内容展示在EditText上
dismiss();//如果已经选择了隐藏起来
start(binding.editview.getText().toString());
start(binding.toolbar.getText().toString());
});
Object o = new Object();
binding.editview.addTextChangedListener(new Edit.TextWatcher() {
binding.searchview.getEditText().addTextChangedListener(new Edit.TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
binding.editview.iskong();
if (TextUtils.isEmpty(s)) {
listPopupWindow.setVisibility(View.GONE);
return;
@ -135,7 +128,8 @@ public class activity_search extends FragmentActivity<ActivitySearchBinding> {
@Override
public void run() {
synchronized (o) {
String hq = wl.hq("/search/suggest?keywords=" + s + "&type=mobile");
String hq = com.muqingbfq.mq.wl.
hq("/search/suggest?keywords=" + s + "&type=mobile");
try {
JSONArray jsonArray = new JSONObject(hq).getJSONObject("result")
.getJSONArray("allMatch");
@ -153,18 +147,46 @@ public class activity_search extends FragmentActivity<ActivitySearchBinding> {
}
}.start();
}
@Override
public void afterTextChanged(Editable s) {
}
});
gj.tcjp(binding.editview.editText);
/* if (binding.toolbar.collapse(contextualToolbar, binding.barlayout)) {
// Clear selection.
return;
}*/
binding.searchview.inflateMenu(R.menu.search);
binding.searchview.setOnMenuItemClickListener(
menuItem -> {
binding.searchview.hide();
start(binding.searchview.getText().toString());
return true;
});
binding.searchview.addTransitionListener(
(searchView, previousState, newState) -> {
if (newState == SearchView.TransitionState.HIDDEN) {
binding.toolbar.setText(searchView.getText());
}
});
binding.searchview
.getEditText()
.setOnEditorActionListener(
(v, actionId, event) -> {
binding.toolbar.setText(binding.searchview.getText());
binding.searchview.hide();
start(binding.searchview.getText().toString());
return false;
});
binding.toolbar.setOnMenuItemClickListener(item -> {
//搜索
start(binding.toolbar.getText().toString());
return true;
});
}
public void dismiss() {
binding.editview.clearFocus();
listPopupWindow.setVisibility(View.GONE);
gj.ycjp(binding.editview.editText);
binding.searchview.hide();
}
private void addSearchRecord(String name) {
@ -204,13 +226,17 @@ public class activity_search extends FragmentActivity<ActivitySearchBinding> {
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int itemId = item.getItemId();
if (binding.searchFragment.getVisibility() == View.VISIBLE) {
binding.searchFragment.setVisibility(View.GONE);
return false;
}
if (itemId == android.R.id.home) {
ActivityCompat.finishAfterTransition(this);
return false;
} else if (itemId == 0) {
start(binding.editview.getText().toString());
start(binding.toolbar.getText().toString());
}
return super.onOptionsItemSelected(item);
return true;
}
public void start(String name) {
@ -269,7 +295,7 @@ public class activity_search extends FragmentActivity<ActivitySearchBinding> {
String keyword = json_list.get(position);
holder.recordTextView.setText(keyword);
holder.recordTextView.setOnClickListener(v -> {
binding.editview.setText(keyword);
binding.toolbar.setText(keyword);
start(keyword);
});
holder.recordTextView.setOnLongClickListener(view -> {
@ -308,6 +334,10 @@ public class activity_search extends FragmentActivity<ActivitySearchBinding> {
}
private void end() {
if (binding.searchview.isShowing()) {
binding.searchview.hide();
return;
}
if (binding.searchRecycler.getVisibility() == View.VISIBLE) {
binding.searchRecycler.setVisibility(View.GONE);
return;

View File

@ -1,12 +1,10 @@
package com.muqingbfq.api;
import android.content.Intent;
import com.mpatric.mp3agic.ID3v2;
import com.mpatric.mp3agic.Mp3File;
import com.muqingbfq.MP3;
import com.muqingbfq.fragment.Media;
import com.muqingbfq.login.user_logs;
import com.muqingbfq.home;
import com.muqingbfq.main;
import com.muqingbfq.mq.gj;
import com.muqingbfq.mq.wj;
@ -55,9 +53,9 @@ public class url extends Thread {
if (json.getInt("code") == -460) {
String message = json.getString("message");
main.handler.post(() -> {
gj.ts(main.application, message);
main.application.startActivity(new Intent(main.application
, user_logs.class));
gj.ts(home.activity, message);
home.activity.startActivity(new android.content.Intent(home.activity
, com.muqingbfq.login.user_logs.class));
});
return null;
}

View File

@ -3,6 +3,7 @@ package com.muqingbfq;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
@ -10,7 +11,10 @@ import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
@ -18,13 +22,12 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.widget.SeekBar;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.palette.graphics.Palette;
import com.bumptech.glide.Glide;
@ -33,7 +36,6 @@ import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target;
import com.google.android.material.slider.Slider;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.mpatric.mp3agic.ID3v2;
@ -56,6 +58,23 @@ public class bfq extends AppCompatActivity<ActivityBfqBinding>
public MP3 mp3;
public boolean isplay = true;
GestureDetector gestureDetector;
int seekbarH = 0;
private void lrc(View v) {
// 隐藏view2并显示view1的动画效果
v.animate()
.alpha(0.0f)
.setDuration(500)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
v.setVisibility(View.GONE);
binding.cardview.setVisibility(View.VISIBLE);
binding.cardview.setAlpha(0.0f);
binding.cardview.animate().alpha(1.0f).setDuration(500).setListener(null);
}
});
}
@SuppressLint("ClickableViewAccessibility")
private void setLrc() {
@ -66,48 +85,66 @@ public class bfq extends AppCompatActivity<ActivityBfqBinding>
if (!gj.isTablet(this)) {
layoutParams.height = (int) (main.k / 1.3f);
layoutParams.width = (int) (main.k / 1.3f);
binding.fragmentBfq.setOnTouchListener((v, event) -> bfq.super.onTouchEvent(event));
binding.lrcView.setOnClickListener(this::lrc);
binding.lrcView.setOnTapListener((view, x, y) -> {
// 隐藏view2并显示view1的动画效果
view.animate()
.alpha(0.0f)
.setDuration(500)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
view.setVisibility(View.GONE);
binding.cardview.setVisibility(View.VISIBLE);
binding.cardview.setAlpha(0.0f);
binding.cardview.animate().alpha(1.0f).setDuration(500).setListener(null);
}
});
});
binding.lrcView.setOnSingerClickListener(() -> lrc(binding.lrcView));
// binding.lrcView.setTextGravity(GRAVITY_LEFT)
binding.lrcView.setNormalTextSize(80f);
binding.lrcView.setCurrentTextSize(100f);
binding.lrcView.setTranslateTextScaleValue(0.8f);
binding.lrcView.setHorizontalOffset(-50f);
binding.lrcView.setHorizontalOffsetPercent(0.5f);
binding.lrcView.setItemOffsetPercent(0.5f);
binding.lrcView.setIsDrawTranslation(true);
binding.lrcView.setIsEnableBlurEffect(true);
} else {
layoutParams.height = (int) (main.g / 2.0f);
layoutParams.width = (int) (main.g / 2.0f);
}
binding.cardview.setLayoutParams(layoutParams);
binding.lrcView.
setDraggable(true, (a, time) -> {
binding.lrcView.setDraggable(true, time -> {
bfqkz.mt.seekTo((int) time);
return false;
});
binding.tdt.addOnChangeListener((slider, value, fromUser) ->
setTime_b(bfq_an.getTime((long) value)));
binding.tdt.addOnSliderTouchListener(new Slider.OnSliderTouchListener() {
binding.tdt.setThumb(null);
binding.tdt.post(() -> seekbarH = binding.tdt.getHeight());
binding.tdt.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onStartTrackingTouch(@NonNull Slider slider) {
// 拖动条移动中
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// 当进度发生变化时执行操作
setTime_b(bfq_an.getTime(progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// 当开始拖动滑块时执行操作
// 创建 ValueAnimator 对象实现进度条高度的平滑过渡
ValueAnimator animator = ValueAnimator.ofInt(seekbarH,
seekbarH + 30);
animator.addUpdateListener(animation -> {
seekBar.getLayoutParams().height = (int) animation.getAnimatedValue();
seekBar.requestLayout();
});
animator.setDuration(200); // 设置动画持续时间为 200 毫秒
animator.start(); // 开始执行动画
isplay = false;
}
@Override
public void onStopTrackingTouch(@NonNull Slider slider) {
// 播放音乐到指定位置
public void onStopTrackingTouch(SeekBar seekBar) {
// 当停止拖动滑块时执行操作
isplay = true;
bfqkz.mt.seekTo((int) slider.getValue());
// 创建 ValueAnimator 对象实现恢复进度条高度的平滑过渡
ValueAnimator animator = ValueAnimator.ofInt(seekbarH + 30,
seekbarH);
animator.addUpdateListener(animation -> {
seekBar.getLayoutParams().height = (int) animation.getAnimatedValue();
seekBar.requestLayout();
});
animator.setDuration(200); // 设置动画持续时间为 200 毫秒
animator.start(); // 开始执行动画
bfqkz.mt.seekTo(seekBar.getProgress());
}
});
}
@ -120,17 +157,39 @@ public class bfq extends AppCompatActivity<ActivityBfqBinding>
context.startActivity(intent);
}
ObjectAnimator rotateAnimation;
private void Animation() {
if (bfqkz.mt.isPlaying()) {
if (rotateAnimation.isPaused()) {
rotateAnimation.resume();
} else {
rotateAnimation.start();
}
} else {
rotateAnimation.pause();
}
}
@SuppressLint("ClickableViewAccessibility")
@Override
protected void UI(@Nullable Bundle savedInstanceState) {
gestureDetector = new GestureDetector(this, this);
setLrc();
rotateAnimation = ObjectAnimator.ofFloat(binding.cardview
, "rotation", 0f, 360f);
rotateAnimation.setDuration(30000); // 设置动画持续时间单位为毫秒
rotateAnimation.setRepeatCount(ObjectAnimator.INFINITE); // 设置重复次数为无限
rotateAnimation.setInterpolator(new LinearInterpolator()); // 设置插值器这里使用线性插值器
rotateAnimation.start();
binding.kg.setOnClickListener(v -> {
if (bfqkz.mt.isPlaying()) {
bfqkz.mt.pause();
setbf(false);
} else {
bfqkz.mt.start();
setbf(true);
}
Animation();
});
binding.xyq.setOnClickListener(v -> bfq_an.xyq());
binding.syq.setOnClickListener(v -> bfq_an.syq());
@ -178,6 +237,21 @@ public class bfq extends AppCompatActivity<ActivityBfqBinding>
Intent intent = getIntent();
mp3 = (MP3) intent.getSerializableExtra("MP3");
new thread().start();
binding.fragmentBfq.setOnTouchListener((v, event) -> {
gestureDetector.onTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP) {
if (binding.getRoot().getRootView().getTranslationY() > (main.g / 2.0f)) {
finish();
return true;
}
ObjectAnimator animator = ObjectAnimator.ofFloat(binding.getRoot().getRootView()
, "y", binding.getRoot().getRootView().getTranslationY(), 0);
animator.setDuration(500);
animator.start();
}
return true;
});
}
private class toolbar implements View.OnClickListener {
@ -211,28 +285,12 @@ public class bfq extends AppCompatActivity<ActivityBfqBinding>
if (mp3 != null) {
sx();
}
if (bfqkz.mt != null && bfqkz.mt.isPlaying()) {
binding.kg.setImageResource(R.drawable.bf);
}
setbf(bfqkz.mt.isPlaying());
Animation();
});
main.handler.post(runnable);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
gestureDetector.onTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP) {
if (binding.getRoot().getRootView().getTranslationY() > (main.g / 2.0f)) {
finish();
return true;
}
ObjectAnimator animator = ObjectAnimator.ofFloat(binding.getRoot().getRootView()
, "y", binding.getRoot().getRootView().getTranslationY(), 0);
animator.setDuration(500);
animator.start();
}
return super.onTouchEvent(event);
}
public void sx() {
@ -269,12 +327,12 @@ public class bfq extends AppCompatActivity<ActivityBfqBinding>
}
public void setlike(boolean bool) {
int color = R.color.text;
if (bool) {
color = android.R.color.holo_red_dark;
}
binding.like.setImageTintList(ContextCompat.
getColorStateList(binding.getRoot().getContext(), color));
getColorStateList(binding.getRoot().getContext(), android.R.color.holo_red_dark));
} else {
binding.like.setImageTintList(ColorStateList.valueOf(ColorTint));
}
islike = bool;
}
@ -299,6 +357,7 @@ public class bfq extends AppCompatActivity<ActivityBfqBinding>
setImageBitmap();
}
if (bfqkz.mt.isPlaying() != isPlaying) {
setbf(bfqkz.mt.isPlaying());
}
if (bfqkz.like_bool != islike) {
@ -307,7 +366,7 @@ public class bfq extends AppCompatActivity<ActivityBfqBinding>
if (!Objects.equals(bfqkz.lrc, lrc)) {
lrc = bfqkz.lrc;
String[] strings = Media.loadLyric();
binding.lrcView.loadLrc(strings[0], strings[1]);
binding.lrcView.loadLyric(strings[0], strings[1]);
}
main.handler.postDelayed(this, 1000); // 每秒更新一次进度
}
@ -362,7 +421,6 @@ public class bfq extends AppCompatActivity<ActivityBfqBinding>
@NonNull DataSource dataSource,
boolean isFirstResource) {
color(resource);
return false;
}
}).into(binding.cardview.imageView);
@ -373,23 +431,47 @@ public class bfq extends AppCompatActivity<ActivityBfqBinding>
Palette.from(bitmap)
.maximumColorCount(10)
.generate(palette -> {
// 获取图片中有活力的亮色
int dominantSwatch = palette.getLightVibrantColor(Color.WHITE);
// 获取图片中柔和的亮色
int lightMutedColor = palette.getLightMutedColor(Color.GRAY);
GradientDrawable gradientDrawable = new GradientDrawable(
GradientDrawable.Orientation.BOTTOM_TOP, // 渐变方向从上到下
new int[]{Color.BLACK, lightMutedColor} // 渐变颜色数组
new int[]{lightMutedColor, dominantSwatch} // 渐变颜色数组
);
// 设置渐变背景的形状为矩形
int vibrantColor = palette.getVibrantColor(Color.BLACK);
setTint(vibrantColor);
gradientDrawable.setShape(GradientDrawable.RECTANGLE);
// trackColorInactive
// 创建颜色列表
ColorStateList trackInactiveTintList = ColorStateList
.valueOf(ColorUtils.blendARGB(lightMutedColor
, Color.WHITE, 0.5f));
binding.tdt.setTrackInactiveTintList(trackInactiveTintList);
binding.getRoot().setBackground(gradientDrawable);
});
}
private int ColorTint = Color.WHITE;
private void setTint(int color) {
this.ColorTint = color;
ColorStateList colorStateList = ColorStateList.valueOf(color);
binding.kg.setImageTintList(colorStateList);
binding.syq.setImageTintList(colorStateList);
binding.xyq.setImageTintList(colorStateList);
binding.bfqListMp3.setImageTintList(colorStateList);
binding.control.setImageTintList(colorStateList);
binding.like.setImageTintList(colorStateList);
binding.download.setImageTintList(colorStateList);
binding.image2.setImageTintList(colorStateList);
binding.name.setTextColor(color);
binding.zz.setTextColor(color);
binding.timeA.setTextColor(color);
binding.timeB.setTextColor(color);
Drawable progressDrawable = binding.tdt.getProgressDrawable();
LayerDrawable layerDrawable = (LayerDrawable) progressDrawable;
Drawable progress = layerDrawable.findDrawableByLayerId(android.R.id.progress);
progress.setColorFilter(color, PorterDuff.Mode.SRC_IN);
// 设置进度条背景的颜色
/* Drawable background = layerDrawable.findDrawableByLayerId(android.R.id.background);
background.setColorFilter(Color.GRAY, PorterDuff.Mode.SRC_IN);*/
}
@Override
public void finish() {
super.finish();
@ -405,18 +487,14 @@ public class bfq extends AppCompatActivity<ActivityBfqBinding>
}
public void setMax(int max) {
binding.tdt.setValueTo(Math.max(0, max));
binding.tdt.setMax(Math.max(0, max));
}
public void Progress(int progress) {
if (binding.tdt.getValueTo() < progress) {
return;
// 处理超出范围的情况
int min = Math.min(progress, binding.tdt.getMax());
binding.tdt.setProgress(min);
binding.lrcView.updateTime(min, true);
}
binding.tdt.setValue(progress);
binding.lrcView.updateTime(progress);
}
@Override
public boolean onDown(@NonNull MotionEvent e) {
@ -471,9 +549,9 @@ public class bfq extends AppCompatActivity<ActivityBfqBinding>
@Override
public boolean onScroll(@NonNull MotionEvent e1, @NonNull MotionEvent e2,
float distanceX, float distanceY) {
if (binding.lrcView.getVisibility() == View.VISIBLE) {
/* if (binding.lrcView.getVisibility() == View.VISIBLE) {
return false;
}
}*/
float y = binding.getRoot().getRootView().getTranslationY() - distanceY;
y = Math.max(0, y);
//移动的距离

View File

@ -25,7 +25,8 @@ import java.util.ArrayList;
import java.util.List;
public class bfqkz extends MediaBrowserServiceCompat {
public static MediaPlayer mt = new MediaPlayer();
public final static MediaPlayer mt = new MediaPlayer();
public static List<MP3> list = new ArrayList<>();
//保存原始list顺序
public static List<MP3> list_baocun = new ArrayList<>();

View File

@ -28,12 +28,11 @@ import java.util.List;
public class fragment_clean extends FragmentActivity<ActivityCleanBinding> {
List<String[]> list = new ArrayList<>();
List<String> list_box = new ArrayList<>();
ActivityCleanBinding binding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityCleanBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setContentView();
setToolbar();
UI();
}
@ -117,7 +116,7 @@ public class fragment_clean extends FragmentActivity<ActivityCleanBinding> {
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
} else if (item == menu_deleat) {

View File

@ -1,5 +1,6 @@
package com.muqingbfq.fragment;
import com.dirror.lyricviewx.LyricViewX;
import com.muqingbfq.mq.gj;
import org.json.JSONObject;
@ -17,12 +18,10 @@ public class Media {
a = jsonObject.getJSONObject("lrc").getString("lyric");
b = jsonObject.getJSONObject("tlyric").getString("lyric");
} catch (Exception e) {
gj.sc("Media loadLyric "+e);
gj.sc("Media loadLyric " + e);
}
me.wcy.lrcview.LrcView.Lrc(a, b);
LyricViewX.lrc(a, b);
return new String[]{a, b};
// bfq.lrcView.getLrc();
// bfq.lrcView.loadLrc(a, b);
}
}

View File

@ -50,7 +50,7 @@ public class gd extends com.muqingbfq.mq.FragmentActivity<ActivityGdBinding> {
public static void start(Activity context, String[] str, View view) {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(context,
view, "view");
view, "text");
Intent intent = new Intent(context, gd.class);
intent.putExtra("id", str[0]);
intent.putExtra("name", str[1]);

View File

@ -10,7 +10,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -41,20 +40,24 @@ public class gd_adapter extends Fragment {
List<XM> list = new ArrayList<>();
List<MP3> listmp3 = new ArrayList<>();
FragmentGdBinding binding;
public void toolbar() {
// binding.bar.setupWithDrawer
((AppCompatActivity) requireActivity()).setSupportActionBar(binding.toolbar);
androidx.drawerlayout.widget.DrawerLayout drawerLayout = requireActivity().findViewById(R.id.chct);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
requireActivity(), drawerLayout, binding.toolbar, R.string.app_name, R.string.app_name);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentGdBinding.inflate(getLayoutInflater(), container, false);
//初始化工具栏
((AppCompatActivity) requireActivity()).setSupportActionBar(binding.toolbar);
DrawerLayout drawerLayout = requireActivity().findViewById(R.id.chct);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
getActivity(), drawerLayout, binding.toolbar, R.string.app_name, R.string.app_name);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
toolbar();
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
binding.recyclerview1.setHasFixedSize(true);
@ -122,7 +125,7 @@ public class gd_adapter extends Fragment {
});
mp3list();
binding.editView.setOnClickListener(v -> activity_search.start(getActivity(),v));
binding.toolbar.setOnClickListener(v -> activity_search.start(getActivity(), v));
return binding.getRoot();
}

View File

@ -54,7 +54,7 @@ public class mp3 extends FragmentActivity<ActivityMp3Binding> {
public static void start(Activity context, String[] str, View view) {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(context,
view, "view");
view, "text");
Intent intent = new Intent(context, mp3.class);
intent.putExtra("id", str[0]);
intent.putExtra("name", str[1]);

View File

@ -71,18 +71,22 @@ public class wode extends Fragment {
@SuppressLint("StaticFieldLeak")
public static baseadapter adaper;
public void toolbar() {
((AppCompatActivity) requireActivity()).setSupportActionBar(binding.toolbar);
DrawerLayout drawerLayout = requireActivity().findViewById(R.id.chct);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
requireActivity(), drawerLayout, binding.toolbar, R.string.app_name, R.string.app_name);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentWdBinding.inflate(inflater, container, false);
//初始化工具栏
((AppCompatActivity) requireActivity()).setSupportActionBar(binding.toolbar);
DrawerLayout drawerLayout = getActivity().findViewById(R.id.chct);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
getActivity(), drawerLayout, binding.toolbar, R.string.app_name, R.string.app_name);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
toolbar();
name = binding.text1;
binding.appbar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
boolean isCollapsed = false; // 标记是否处于折叠状态
@ -146,7 +150,7 @@ public class wode extends Fragment {
getContext().startActivity(a);
break;
case "排行榜":
gd.start(getActivity(), new String[]{data, s}, holder.itemView);
gd.start(getActivity(), new String[]{data, s}, holder.textView);
break;
case "API":
EditViewDialog editViewDialog = new EditViewDialog(getContext(), "更换接口API")

View File

@ -1,5 +1,7 @@
package com.muqingbfq;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@ -14,6 +16,7 @@ import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
@ -27,12 +30,17 @@ import java.util.List;
public class home extends com.muqingbfq.mq.AppCompatActivity<ActivityHomeBinding> {
public MediaBrowserCompat mBrowser;
@SuppressLint("StaticFieldLeak")
public static Context activity;
@Override
protected ActivityHomeBinding getViewBindingObject(LayoutInflater layoutInflater) {
return ActivityHomeBinding.inflate(layoutInflater);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
activity = this;
setTheme(R.style.Theme_muqing);
super.onCreate(savedInstanceState);
setContentView(getViewBinding().getRoot());
@ -72,14 +80,12 @@ public class home extends com.muqingbfq.mq.AppCompatActivity<ActivityHomeBinding
}
public static ComponentName componentName;
private class Adaper extends FragmentStateAdapter {
List<Fragment> list = new ArrayList<>();
public Adaper(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
public void UI() {
list.clear();
list.add(new gd_adapter());
list.add(new wode());
}
binding.viewPager.setAdapter(new FragmentStateAdapter(this) {
@NonNull
@Override
public Fragment createFragment(int position) {
@ -90,13 +96,9 @@ public class home extends com.muqingbfq.mq.AppCompatActivity<ActivityHomeBinding
public int getItemCount() {
return list.size();
}
}
public void UI() {
Adaper adapter = new Adaper(this);
binding.viewPager.setAdapter(adapter);
});
binding.viewPager.setSaveEnabled(false);
// ViewPager2 绑定到 TabLayout
// ViewPager2 绑定到 TabLayou
binding.tablayout.setOnItemSelectedListener(item -> {
int itemId = item.getItemId();
if (itemId == R.id.a) {
@ -132,6 +134,7 @@ public class home extends com.muqingbfq.mq.AppCompatActivity<ActivityHomeBinding
editor.putString("listData", jsonList);
editor.apply();
}
@Override
public void onBackPressed() {
moveTaskToBack(true);

View File

@ -27,16 +27,13 @@ import java.util.List;
public class main extends Application {
public static Application application;
public static Handler handler = new Handler(Looper.getMainLooper());
public static String api = "http://139.196.224.229:3000";
public static String http = "http://139.196.224.229/muqing";
public static String api = "https://service-8xjb06vc-1319932248.gz.tencentapigw.com.cn/release";
public static String http = "https://www.muqingkaifazhe.top/muqingbfq.php";
public static int k, g;
public static SharedPreferences sp;
public static SharedPreferences.Editor edit;
public int count = 0;
public static long item = System.currentTimeMillis();
@SuppressLint("HardwareIds")
private int count = 0;
@Override
public void onCreate() {
super.onCreate();
@ -80,7 +77,6 @@ public class main extends Application {
if (wl.Cookie.equals("")) {
new visitor();
}
SharedPreferences theme = getSharedPreferences("theme", MODE_PRIVATE);
@SuppressLint("CommitPrefEdits") SharedPreferences.Editor edit = theme.edit();
int i = theme.getInt("theme", AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
@ -89,7 +85,6 @@ public class main extends Application {
edit.apply();
}
AppCompatDelegate.setDefaultNightMode(i);
String jsonList = this.getSharedPreferences("list", Context.MODE_PRIVATE)
.getString("listData", null); // 获取保存的 JSON 字符串
if (jsonList != null) {
@ -116,12 +111,10 @@ public class main extends Application {
}
}.start();
}
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(@NonNull Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(@NonNull Activity activity) {
if (count == 0) { //后台切换到前台
@ -131,21 +124,16 @@ public class main extends Application {
}
count++;
}
@Override
public void onActivityResumed(@NonNull Activity activity) {
}
@Override
public void onActivityPaused(@NonNull Activity activity) {
}
@Override
public void onActivityStopped(@NonNull Activity activity) {
count--;
if (count == 0) { //后台切换到前台
// gj.sc(">>>>>>>>>>>>>>>>>>>App切到后台");
new Thread(){
@Override
public void run() {
@ -154,7 +142,6 @@ public class main extends Application {
} catch (InterruptedException e) {
e.printStackTrace();
}
// gj.sc(count);
if (count != 0) {
return;
}
@ -173,7 +160,6 @@ public class main extends Application {
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {
}

View File

@ -18,7 +18,6 @@ public class BluetoothMusicController {
this.context = context;
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intentFilter.addAction("android.intent.action.HEADSET_PLUG");
context.registerReceiver(new MyButtonClickReceiver(), intentFilter);
registerHeadsetReceiver();

View File

@ -17,6 +17,8 @@ import android.widget.ImageView;
import androidx.annotation.Nullable;
import com.dirror.lyricviewx.LyricEntry;
import com.dirror.lyricviewx.LyricViewX;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.muqingbfq.R;
@ -27,10 +29,6 @@ import com.muqingbfq.main;
import java.io.File;
import java.lang.reflect.Type;
import me.wcy.lrcview.LrcEntry;
import me.wcy.lrcview.LrcView;
public class FloatingLyricsService extends Service implements View.OnClickListener, View.OnTouchListener {
private WindowManager windowManager;
private View layout;
@ -39,26 +37,17 @@ public class FloatingLyricsService extends Service implements View.OnClickListen
@Override
public void run() {
int index = 0;
for (int i = 0; i < LrcView.mLrcEntryList.size(); i++) {
LrcEntry lineLrc = LrcView.mLrcEntryList.get(i);
for (int i = 0; i < LyricViewX.lyricEntryList.size(); i++) {
LyricEntry lineLrc = LyricViewX.lyricEntryList.get(i);
if (lineLrc.time <= bfqkz.mt.getCurrentPosition()) {
index = i;
} else {
break;
}
}
if (index < LrcView.mLrcEntryList.size()) {
if (index < LyricViewX.lyricEntryList.size()) {
String text;
if (LrcView.mLrcEntryList.size() <= 3) {
for (LrcEntry a : LrcView.mLrcEntryList) {
if (a.time == 5940000 && a.text.equals("纯音乐,请欣赏")) {
text = "纯音乐,请欣赏";
binding.lrcView.setText(text);
return;
}
}
}
LrcEntry currentLrc = LrcView.mLrcEntryList.get(index);
LyricEntry currentLrc = LyricViewX.lyricEntryList.get(index);
text = currentLrc.text;
if (currentLrc.secondText != null) {
text += "\n" + currentLrc.secondText;

View File

@ -5,6 +5,7 @@ import android.view.MenuItem;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.viewbinding.ViewBinding;
import com.jaeger.library.StatusBarUtil;
@ -29,13 +30,19 @@ public abstract class FragmentActivity<ViewBindingType extends ViewBinding>
return super.onOptionsItemSelected(item);
}
public void setToolbar() {
setSupportActionBar(findViewById(R.id.toolbar));
View viewById = findViewById(R.id.toolbar);
if (viewById != null) {
setSupportActionBar((Toolbar) viewById);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
@Override
public void setContentView(int view) {
super.setContentView(view);
}
public void setContentView() {
binding = getViewBindingObject(getLayoutInflater());
setContentView(binding.getRoot());
setToolbar();
}
@ -43,6 +50,5 @@ public abstract class FragmentActivity<ViewBindingType extends ViewBinding>
public void setContentView(View view) {
StatusBarUtil.setTransparent(this);
super.setContentView(view);
setToolbar();
}
}

View File

@ -67,7 +67,7 @@ public class gj {
if (a == null) {
a = "null";
}
Log.d("云音乐", a.toString());
Log.d("打印", a.toString());
floating.addtext(a.toString());
}

View File

@ -12,6 +12,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
@ -41,27 +42,26 @@ import okhttp3.Response;
public class llq extends AppCompatActivity<ActivityLlqBinding> {
WebView web;
@Override
protected ActivityLlqBinding getViewBindingObject(LayoutInflater layoutInflater) {
return ActivityLlqBinding.inflate(layoutInflater);
}
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void UI(@Nullable Bundle savedInstanceState) {
Intent intent = getIntent();
setSupportActionBar(binding.toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
web = findViewById(R.id.webview);
web = binding.webview;
web.getSettings().setJavaScriptEnabled(true);
web.getSettings().setDomStorageEnabled(true);
// 禁用缓存
web.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
web.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
String title = view.getTitle();
setTitle(title);
setSubtitle(url);
setTitle(web.getTitle());
// 在这里获取到了网页的标题
}
});
@ -162,15 +162,9 @@ public class llq extends AppCompatActivity<ActivityLlqBinding> {
});
loadUrl(intent.getStringExtra("url"));
}
private void setSubtitle(String url) {
binding.toolbar.setSubtitle(url);
}
private void loadUrl(String url) {
web.loadUrl(url);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
@ -180,13 +174,11 @@ public class llq extends AppCompatActivity<ActivityLlqBinding> {
gj.ts(this, "权限已授予,请重新执行文件下载操作");
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.llq, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public void onBackPressed() {
if (web.canGoBack()) {
@ -195,8 +187,6 @@ public class llq extends AppCompatActivity<ActivityLlqBinding> {
finish();
}
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int itemId = item.getItemId();
@ -213,4 +203,5 @@ public class llq extends AppCompatActivity<ActivityLlqBinding> {
}
return super.onOptionsItemSelected(item);
}
}

View File

@ -17,18 +17,20 @@ import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import com.colorpicker.ColorPickerView;
import com.colorpicker.builder.ColorPickerDialogBuilder;
import com.dirror.lyricviewx.LyricEntry;
import com.dirror.lyricviewx.LyricViewX;
import com.google.android.material.materialswitch.MaterialSwitch;
import com.google.android.material.slider.Slider;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.muqingbfq.databinding.ActivitySzBinding;
import com.muqingbfq.databinding.ActivitySzSetlrcBinding;
import com.muqingbfq.mq.AppCompatActivity;
import com.muqingbfq.mq.FloatingLyricsService;
import com.muqingbfq.mq.wj;
@ -36,48 +38,40 @@ import java.io.File;
import java.lang.reflect.Type;
import java.util.Locale;
import me.wcy.lrcview.LrcEntry;
import me.wcy.lrcview.LrcView;
public class sz extends AppCompatActivity {
public class sz extends AppCompatActivity<ActivitySzBinding> {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sz);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setTitle(getString(R.string.sz));
UI();
kaifazhe();
protected ActivitySzBinding getViewBindingObject(LayoutInflater layoutInflater) {
return ActivitySzBinding.inflate(layoutInflater);
}
@Override
protected void UI(Bundle bundle) {
setSupportActionBar(binding.toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setTitle(getString(R.string.sz));
kaifazhe();
@SuppressLint("ApplySharedPref")
private void UI() {
MaterialSwitch a1 = findViewById(R.id.switch_a1);
MaterialSwitch a2 = findViewById(R.id.switch_a2);
SharedPreferences theme = getSharedPreferences("theme", MODE_PRIVATE);
@SuppressLint("CommitPrefEdits") SharedPreferences.Editor edit = theme.edit();
int i = theme.getInt("theme", AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
if (i == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) {
a1.setChecked(true);
a2.setEnabled(false);
binding.switchA1.setChecked(true);
binding.switchA2.setEnabled(false);
} else {
a1.setChecked(false);
a2.setEnabled(true);
a2.setChecked(i == AppCompatDelegate.MODE_NIGHT_YES);
binding.switchA1.setChecked(false);
binding.switchA2.setEnabled(true);
binding.switchA2.setChecked(i == AppCompatDelegate.MODE_NIGHT_YES);
}
a1.setOnCheckedChangeListener((compoundButton, b) -> {
binding.switchA1.setOnCheckedChangeListener((compoundButton, b) -> {
if (b) {
// 跟随系统设置切换颜色模式
int ms = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
AppCompatDelegate.setDefaultNightMode(ms);
edit.putInt("theme", ms);
edit.commit();
edit.apply();
}
a2.setEnabled(!b);
binding.switchA2.setEnabled(!b);
});
a2.setOnCheckedChangeListener((compoundButton, b) -> {
binding.switchA2.setOnCheckedChangeListener((compoundButton, b) -> {
if (compoundButton.isEnabled()) {
int ms;
if (b) {
@ -91,8 +85,6 @@ public class sz extends AppCompatActivity {
}
});
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == android.R.id.home) {
@ -100,7 +92,6 @@ public class sz extends AppCompatActivity {
}
return super.onOptionsItemSelected(item);
}
ActivityResultLauncher<Intent> intent = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
@ -108,9 +99,9 @@ public class sz extends AppCompatActivity {
com.muqingbfq.mq.floating.start(sz.this);
}
});
public void kaifazhe() {
MaterialSwitch materialSwitch = findViewById(R.id.switch_kfz);
/* MaterialSwitch materialSwitch = findViewById(R.id
.switch_kfz);
materialSwitch.setOnCheckedChangeListener((compoundButton, b) -> {
if (b) {
if (!Settings.canDrawOverlays(this)) {
@ -123,10 +114,8 @@ public class sz extends AppCompatActivity {
} else {
com.muqingbfq.mq.floating.end(sz.this);
}
});
});*/
}
public static class setlrc extends Fragment implements Slider.OnSliderTouchListener,
Slider.OnChangeListener {
ActivityResultLauncher<Intent> LyricsService =
@ -142,26 +131,17 @@ public class sz extends AppCompatActivity {
public void run() {
if (bfqkz.mt.isPlaying()) {
int index = 0;
for (int i = 0; i < LrcView.mLrcEntryList.size(); i++) {
LrcEntry lineLrc = LrcView.mLrcEntryList.get(i);
for (int i = 0; i < LyricViewX.lyricEntryList.size(); i++) {
LyricEntry lineLrc = LyricViewX.lyricEntryList.get(i);
if (lineLrc.time <= bfqkz.mt.getCurrentPosition()) {
index = i;
} else {
break;
}
}
if (index < LrcView.mLrcEntryList.size()) {
if (index < LyricViewX.lyricEntryList.size()) {
String text;
if (LrcView.mLrcEntryList.size() <= 3) {
for (LrcEntry a : LrcView.mLrcEntryList) {
if (a.time == 5940000 && a.text.equals("纯音乐,请欣赏")) {
text = "纯音乐,请欣赏";
binding.lrctext.setText(text);
return;
}
}
}
LrcEntry currentLrc = LrcView.mLrcEntryList.get(index);
LyricEntry currentLrc = LyricViewX.lyricEntryList.get(index);
text = currentLrc.text;
if (currentLrc.secondText != null) {
text += "\n" + currentLrc.secondText;
@ -207,11 +187,11 @@ public class sz extends AppCompatActivity {
binding.lrctext.setTextColor(selectedColor);
FloatingLyricsService.baocun(setup);
})
.setNegativeButton("取消",null)
.setNegativeButton("取消", null)
.build()
.show());
binding.textSlide1.setText(String.valueOf(setup.size));
binding.textSlide2.setText(String.format(Locale.US,"%.2f",setup.Alpha));
binding.textSlide2.setText(String.format(Locale.US, "%.2f", setup.Alpha));
if (setup.i != 0) {
binding.switchA1.setChecked(true);
}
@ -282,10 +262,10 @@ public class sz extends AppCompatActivity {
setup.size,
getResources().getDisplayMetrics()));
binding.textSlide1.setText(String.valueOf(setup.size));
}else if (slider == binding.slide2) {
} else if (slider == binding.slide2) {
setup.Alpha = value;
binding.lrctext.setAlpha(value);
binding.textSlide2.setText(String.format(Locale.US,"%.2f", value));
binding.textSlide2.setText(String.format(Locale.US, "%.2f", value));
}
}
}

View File

@ -9,6 +9,8 @@ import android.text.NoCopySpan;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
@ -19,6 +21,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import com.google.android.material.textfield.TextInputLayout;
import com.muqingbfq.R;
public class Edit extends LinearLayout {
@ -44,6 +47,8 @@ public class Edit extends LinearLayout {
public EditText editText;
private void initView() {
TextInputLayout layout = new TextInputLayout(getContext());
// layout.clearIconDrawable
setGravity(Gravity.CENTER_VERTICAL);
setBackgroundResource(R.drawable.ui_editview);
setPadding(30, 0, 30, 0);
@ -52,28 +57,29 @@ public class Edit extends LinearLayout {
editText.setHint("搜索");
editText.setSingleLine(true);
editText.setBackground(null);
editText.setTransitionName("edit");
Drawable startIcon = ContextCompat.getDrawable(getContext(), R.drawable.sousuo);
startIcon.setTint(ContextCompat.getColor(getContext(),
R.color.text_tm));
Drawable endIcon = ContextCompat.getDrawable(getContext(), R.drawable.chahao);
editText.setCompoundDrawablesRelativeWithIntrinsicBounds(startIcon, null, endIcon, null);
editText.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
// editText.passwordToggleEnabled
addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence var1, int var2, int var3, int var4) {
}
@Override
public void onTextChanged(CharSequence var1, int var2, int var3, int var4) {
iskong();
}
@Override
public void afterTextChanged(Editable var1) {
}
});
ImageView imageView = new ImageView(getContext());
imageView.setImageResource(R.drawable.sousuo);
imageView.setImageTintList(ContextCompat.getColorStateList(getContext(),
R.color.text_tm));
addView(imageView, (int) TypedValue.applyDimension(TypedValue.
COMPLEX_UNIT_DIP, 26, getResources().getDisplayMetrics())
, (int) TypedValue.applyDimension(TypedValue.
@ -106,23 +112,15 @@ public class Edit extends LinearLayout {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.Edit);
boolean isEnabled = a.getBoolean(R.styleable.Edit_Enabled, true);
if (!isEnabled) {
removeView(editText);
removeView(imageView);
removeView(chahao);
TextView textView = new TextView(getContext());
textView.setTextColor(editText.getHintTextColors());
textView.setText("搜索");
// px 值转换为 sp
float v = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_PX,
editText.getTextSize(),
getResources().getDisplayMetrics()
) / getResources().getDisplayMetrics().scaledDensity;
textView.setTextSize(v);
setGravity(Gravity.CENTER);
addView(textView);
textView.setPadding(26, 26, 26, 26);
// editText.setGravity(Gravity.CENTER);
editText.setFocusable(false);
editText.setFocusableInTouchMode(false);
// editText.setEnabled(false);
editText.setClickable(false);
}
a.recycle();
}

View File

@ -2,8 +2,8 @@
xmlns:aapt="http://schemas.android.com/aapt"
android:viewportWidth="24"
android:viewportHeight="24"
android:width="128dp"
android:height="128dp">
android:width="26dp"
android:height="26dp">
<path
android:fillColor="#CCCCCC"
android:pathData="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12z" />

View File

@ -1,8 +1,8 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:viewportWidth="24"
android:viewportHeight="24"
android:width="128dp"
android:height="128dp">
android:width="26dp"
android:height="26dp">
<path
android:pathData="M12 21.35l-1.45 -1.32C5.4 15.36 2 12.27 2 8.5C2 5.41 4.42 3 7.5 3c1.74 0 3.41 0.81 4.5 2.08C13.09 3.81 14.76 3 16.5 3C19.58 3 22 5.41 22 8.5c0 3.77 -3.4 6.86 -8.55 11.53z"
android:fillColor="#000000" />

View File

Before

Width:  |  Height:  |  Size: 438 B

After

Width:  |  Height:  |  Size: 438 B

View File

@ -0,0 +1,24 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<corners android:radius="16dp" />
<size
android:width="100dp"
android:height="1dp" />
<solid android:color="#5CCCCCCC" />
</shape>
</item>
<item android:id="@android:id/progress">
<scale android:scaleWidth="100%">
<shape android:shape="rectangle">
<corners android:radius="16dp" />
<size
android:width="100dp"
android:height="1dp" />
<solid android:color="#FFFFFF" />
</shape>
</scale>
</item>
</layer-list>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="36dp"
android:width="36dp"
android:height="26dp"
android:width="26dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path

View File

@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/background" />
<item android:top="88.0dip">
<item>
<bitmap
android:gravity="center|top"
android:src="@mipmap/logo" />
android:src="@mipmap/icon"
android:scaleType="center"/>
</item>
</layer-list>

View File

@ -71,7 +71,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<me.wcy.lrcview.LrcView
<com.dirror.lyricviewx.LyricViewX
android:id="@+id/lrcView"
android:layout_width="0dp"
android:layout_height="match_parent"
@ -199,16 +199,11 @@
android:text="@string/_00_00"
android:textSize="20sp" />
<com.google.android.material.slider.Slider
<SeekBar
android:id="@+id/tdt"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:labelBehavior="gone"
app:thumbColor="#E6E6E6"
app:trackColorActive="#CCCCCC"
tools:ignore="SpeakableTextPresentCheck" />
android:layout_weight="1" />
<TextView
android:id="@+id/time_b"
android:layout_width="wrap_content"

View File

@ -8,41 +8,6 @@
android:fitsSystemWindows="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="10dp">
<ImageView
android:id="@+id/image1"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginTop="3dp"
android:src="@drawable/end"
app:tint="#F1F1F1" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal">
<com.muqingbfq.view.Text
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="歌曲"
android:textColor="#F1F1F1"
android:textSize="26sp"
android:visibility="visible" />
</LinearLayout>
<ImageView
android:id="@+id/image2"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_marginTop="3dp"
android:src="@drawable/abc_ic_menu_share_mtrl_alpha"
app:tint="#F1F1F1" />
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/fragment_bfq"
android:layout_width="match_parent"
@ -50,57 +15,61 @@
android:layout_weight="1"
android:orientation="vertical">
<LinearLayout
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="10dp"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/image1"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginTop="3dp"
android:src="@drawable/end"
app:tint="@color/tint_image"
tools:ignore="ContentDescription" />
</LinearLayout>
<com.muqingbfq.view.CardImage
android:id="@+id/cardview"
android:layout_width="256dp"
android:layout_height="256dp"
app:cardCornerRadius="16dp"
app:cardUseCompatPadding="true"
app:cardBackgroundColor="@color/tm"
app:cardCornerRadius="180dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toBottomOf="@id/toolbar" />
<me.wcy.lrcview.LrcView
<com.dirror.lyricviewx.LyricViewX
android:id="@+id/lrcView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
app:lrcCurrentTextColor="#FFFFFF"
app:lrcNormalTextColor="#FFFDFD"
app:lrcTimelineTextColor="#FFFFFF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:lrcCurrentTextColor="#EEEEEE"
app:lrcNormalTextColor="#CCCCCC"
app:lrcTimelineTextColor="#EEEEEE"
app:lrcNormalTextSize="16sp"
app:lrcTextSize="20sp" />
app:layout_constraintTop_toBottomOf="@id/toolbar" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="6dp"
android:paddingBottom="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginEnd="6dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="10dp"
android:layout_marginBottom="10dp"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@id/tdt"
app:layout_constraintEnd_toEndOf="parent"
app:tint="#CCCCCC">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="6dp"
android:layout_weight="1"
android:orientation="vertical">
app:layout_constraintEnd_toEndOf="parent">
<com.muqingbfq.view.Text
android:id="@+id/name"
@ -108,9 +77,9 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/name"
android:textColor="#CCCCCC"
android:textStyle="bold"
android:textSize="26sp" />
android:textColor="@color/tint_image"
android:textSize="26sp"
android:textStyle="bold" />
<com.muqingbfq.view.Text
android:id="@+id/zz"
@ -118,32 +87,53 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/zz"
android:textColor="#CCCCCC"
android:textColor="@color/tint_image"
android:textSize="20sp" />
</LinearLayout>
<ImageView
android:id="@+id/like"
android:layout_width="36dp"
android:layout_height="36dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/like"
app:tint="#CCCCCC"
tools:ignore="ContentDescription" />
</LinearLayout>
<SeekBar
android:id="@+id/tdt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:background="@null"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:progressDrawable="@drawable/progress"
android:theme="@null"
app:layout_constraintBottom_toTopOf="@id/time_a" />
<TextView
android:id="@+id/time_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/_00_00"
android:textColor="@color/tint_image"
app:layout_constraintBottom_toTopOf="@id/linearLayout3"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/time_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:text="@string/_00_00"
android:textColor="@color/tint_image"
app:layout_constraintBottom_toTopOf="@id/linearLayout3"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.flexbox.FlexboxLayout
android:id="@+id/linearLayout3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginBottom="26dp"
android:orientation="horizontal"
app:alignItems="center"
app:flexDirection="row"
app:justifyContent="space_around"
app:layout_constraintBottom_toTopOf="@+id/download"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="6dp">
app:layout_constraintBottom_toTopOf="@+id/layout2"
tools:ignore="MissingConstraints">
<ImageView
android:id="@+id/control"
@ -151,7 +141,7 @@
android:layout_height="36dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/mt_sx"
app:tint="#CCCCCC"
app:tint="@color/tint_image"
tools:ignore="ContentDescription" />
<ImageView
@ -160,16 +150,17 @@
android:layout_height="36dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/syq"
app:tint="#CCCCCC"
app:tint="@color/tint_image"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/kg"
android:layout_width="46dp"
android:layout_height="46dp"
android:layout_width="66dp"
android:layout_height="66dp"
android:background="?selectableItemBackgroundBorderless"
android:src="@drawable/zt"
app:tint="#CCCCCC"
app:tint="@color/tint_image"
tools:ignore="ContentDescription" />
<ImageView
@ -178,7 +169,7 @@
android:layout_height="36dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/xyq"
app:tint="#CCCCCC"
app:tint="@color/tint_image"
tools:ignore="ContentDescription" />
<ImageView
@ -187,37 +178,20 @@
android:layout_height="36dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/mplist"
app:tint="#CCCCCC"
app:tint="@color/tint_image"
tools:ignore="ContentDescription" />
</com.google.android.flexbox.FlexboxLayout>
<com.google.android.material.slider.Slider
android:id="@+id/tdt"
<com.google.android.flexbox.FlexboxLayout
android:id="@+id/layout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:labelBehavior="gone"
app:layout_constraintBottom_toTopOf="@id/time_a"
app:thumbColor="#E6E6E6"
app:trackColorActive="#CCCCCC"
tools:ignore="SpeakableTextPresentCheck" />
<TextView
android:id="@+id/time_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="@string/_00_00"
app:layout_constraintBottom_toTopOf="@id/linearLayout3"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/time_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="@string/_00_00"
app:layout_constraintBottom_toTopOf="@id/linearLayout3"
app:layout_constraintEnd_toEndOf="parent" />
app:alignItems="center"
app:flexDirection="row"
app:justifyContent="space_around"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageView
android:id="@+id/download"
@ -225,12 +199,29 @@
android:layout_height="36dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/download"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:tint="#CCCCCC"
app:tint="@color/tint_image"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/like"
android:layout_width="36dp"
android:layout_height="36dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/like"
app:tint="@color/tint_image"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/image2"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_marginTop="3dp"
android:src="@drawable/abc_ic_menu_share_mtrl_alpha"
app:tint="@color/tint_image"
tools:ignore="ContentDescription" />
</com.google.android.flexbox.FlexboxLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

View File

@ -14,7 +14,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="26sp"
android:transitionName="view"
android:transitionName="text"
android:textColor="@color/text"/>
</com.google.android.material.appbar.MaterialToolbar>

View File

@ -1,22 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ProgressBar
android:id="@+id/webViewProgressBar"
style="?android:attr/progressBarStyleHorizontal"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="6dp"
android:indeterminate="false"
android:max="100" />
</com.google.android.material.appbar.AppBarLayout>
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -8,7 +8,6 @@
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:transitionName="view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@ -22,6 +21,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/text"
android:transitionName="text"
android:textSize="26sp" />
<EditText

View File

@ -1,25 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context=".activity_search">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.search.SearchView
android:id="@+id/searchview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="@string/search"
app:layout_anchor="@id/toolbar">
<ListView
android:id="@+id/search_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.google.android.material.search.SearchView>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/barlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.muqingbfq.view.Edit
android:id="@+id/editview"
<com.google.android.material.search.SearchBar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:transitionName="view"
android:enabled="false"/>
</com.google.android.material.appbar.MaterialToolbar>
app:defaultMarginsEnabled="true"
app:hideNavigationIcon="false"
app:navigationIcon="@drawable/end"
android:transitionName="edit"
android:hint="@string/search"/>
</com.google.android.material.appbar.AppBarLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
android:layout_weight="1">
<LinearLayout
android:id="@+id/xxbj1"
@ -43,8 +58,9 @@
android:id="@+id/deleat"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginEnd="16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:layout_marginEnd="10dp"
app:tint="@color/text"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/deleat"
android:src="@drawable/delete" />
</LinearLayout>
@ -60,21 +76,15 @@
android:name="com.muqingbfq.fragment.search"
android:visibility="gone"
tools:layout="@layout/fragment_search" />
<ListView
android:id="@+id/search_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:colorBackground"
android:visibility="gone"/>
</RelativeLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/bfq_db"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@color/bj"
android:layout_gravity="bottom"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
android:name="com.muqingbfq.fragment.bfq_db"
tools:layout="@layout/fragment_bfq_db" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -4,8 +4,8 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context=".sz">
<com.google.android.material.appbar.MaterialToolbar
@ -16,13 +16,13 @@
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:layout_marginHorizontal="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
@ -32,45 +32,32 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="主题模式"
android:textSize="20sp" />
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
android:text="主题"/>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switch_a1"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="true"
android:text="根据系统" />
android:textSize="20sp"
android:text="跟随系统模式来选择" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switch_a2"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="26dp"
android:textSize="20sp"
android:text="深色模式" />
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switch_kfz"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开发者模式" />
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
android:text="歌词"/>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_setlrc"

View File

@ -5,21 +5,16 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="歌词调节"
android:textSize="20sp" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardUseCompatPadding="true">
app:cardUseCompatPadding="true"
app:contentPadding="10dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="6dp">
android:layout_height="wrap_content">
<TextView
android:id="@+id/lrctext"
@ -92,14 +87,15 @@
</LinearLayout>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switch_a1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="歌词开关"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/layout2" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switch_a1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="歌词开关"
android:textSize="20sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/layout2" />
</LinearLayout>

View File

@ -8,23 +8,20 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
<com.google.android.material.search.SearchBar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.muqingbfq.view.Edit
android:id="@+id/editView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:Enabled="false"
tools:ignore="TouchTargetSizeCheck" />
</com.google.android.material.appbar.MaterialToolbar>
android:transitionName="edit"
app:layout_scrollFlags="exitUntilCollapsed"
android:hint="@string/search"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:layout_marginHorizontal="10dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
@ -34,17 +31,14 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="6dp"
android:text="每日趣荐"
android:textSize="26sp"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardUseCompatPadding="true"
app:contentPadding="6dp">
app:cardUseCompatPadding="true">
<ProgressBar
android:id="@+id/recyclerview1_bar"
@ -55,7 +49,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nullPlaylists"
android:textSize="26sp"
android:textSize="16sp"
android:padding="6dp"
android:visibility="gone"
android:layout_centerHorizontal="true"/>
@ -72,17 +66,14 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="6dp"
android:text="每日一首"
android:textSize="26sp"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardUseCompatPadding="true"
app:contentPadding="6dp">
app:cardUseCompatPadding="true">
<ProgressBar
android:id="@+id/recyclerview2_bar"
@ -93,7 +84,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nullPlaylists"
android:textSize="26sp"
android:textSize="16sp"
android:padding="6dp"
android:visibility="gone"
android:layout_centerHorizontal="true"/>

View File

@ -20,5 +20,6 @@
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:transitionName="text"
android:text="@string/app_name"/>
</LinearLayout>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,12 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="LrcView">
<!--声明MyTextView需要使用系统定义过的text属性,注意前面需要加上android命名-->
<attr name="TextColor" format="color" />
<attr name="Lrcline" format="boolean" />
<attr name="addOnGlobalLayoutListener" format="boolean" />
</declare-styleable>
<declare-styleable name="ColorPickerPreference">
<attr name="alphaSlider" format="boolean"/>
<attr name="lightnessSlider" format="boolean"/>
@ -33,4 +26,31 @@
<declare-styleable name="Edit">
<attr name="Enabled" format="boolean" />
</declare-styleable>
<declare-styleable name="LyricView">
<attr name="lrcTextSize" format="dimension"/>
<attr name="lrcNormalTextSize" format="dimension"/>
<attr name="lrcSentenceDividerHeight" format="dimension"/>
<attr name="lrcTranslateDividerHeight" format="dimension"/>
<attr name="lrcNormalTextColor" format="reference|color"/>
<attr name="lrcCurrentTextColor" format="reference|color"/>
<attr name="lrcTimelineTextColor" format="reference|color"/>
<attr name="lrcAnimationDuration" format="integer"/>
<attr name="lrcLabel" format="string"/>
<attr name="lrcPadding" format="dimension"/>
<attr name="lrcTimelineColor" format="reference|color"/>
<attr name="lrcTimelineHeight" format="dimension"/>
<attr name="lrcPlayDrawable" format="reference"/>
<attr name="lrcTimeTextColor" format="reference|color"/>
<attr name="lrcTimeTextSize" format="dimension"/>
<attr name="lrcTextGravity">
<enum name="center" value="0"/>
<enum name="left" value="1"/>
<enum name="right" value="2"/>
</attr>
<attr name="lrcTranslateTextScaleValue" format="float"/>
<attr name="lrcHorizontalOffset" format="dimension"/>
<attr name="lrcHorizontalOffsetPercent" format="float"/>
<attr name="lrcItemOffsetPercent" format="float"/>
<attr name="lrcIsDrawTranslation" format="boolean"/>
</declare-styleable>
</resources>

View File

@ -19,4 +19,12 @@
<color name="thumbColor">#625B71</color>
<!-- <color name="button_bj">@color/bj</color>-->
<color name="bj_tint">#FFCCCC</color>
<color name="tint_image">#F1F1F1</color>
<color name="lrc_normal_text_color">#A2A2A2</color>
<color name="lrc_current_text_color">#000000</color>
<color name="lrc_timeline_text_color">#343434</color>
<color name="lrc_timeline_color">#809E9E9E</color>
<color name="lrc_time_text_color">#809E9E9E</color>
</resources>

View File

@ -2,6 +2,17 @@
<resources>
<dimen name="text_margin">16dp</dimen>
<!-- 行间距 -->
<dimen name="default_slider_height">36dp</dimen>
<dimen name="default_slider_margin">24dp</dimen>
<dimen name="default_slider_bar_height">4dp</dimen>
<dimen name="default_slider_handler_radius">10dp</dimen>
<dimen name="default_padding_side">24dp</dimen>
<dimen name="default_preview_height">40dp</dimen>
<dimen name="default_preview_image_height">36dp</dimen>
<dimen name="default_margin_top">20dp</dimen>
<integer name="lrc_animation_duration">1000</integer>
<dimen name="lrc_text_size">16sp</dimen>
<dimen name="lrc_time_text_size">12sp</dimen>
@ -11,13 +22,4 @@
<dimen name="lrc_timeline_height">1dp</dimen>
<dimen name="lrc_drawable_width">30dp</dimen>
<dimen name="lrc_time_width">40dp</dimen>
<dimen name="default_slider_height">36dp</dimen>
<dimen name="default_slider_margin">24dp</dimen>
<dimen name="default_slider_bar_height">4dp</dimen>
<dimen name="default_slider_handler_radius">10dp</dimen>
<dimen name="default_padding_side">24dp</dimen>
<dimen name="default_preview_height">40dp</dimen>
<dimen name="default_preview_image_height">36dp</dimen>
<dimen name="default_margin_top">20dp</dimen>
</resources>

View File

@ -44,4 +44,10 @@
<item></item>
<item></item>
</string-array>
<string-array name="theme">
<item>跟随系统</item>
<item>浅色模式</item>
<item>深色模式</item>
</string-array>
</resources>

View File

@ -1,4 +1,18 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '8.1.0' apply false
id 'org.jetbrains.kotlin.jvm' version '1.8.0'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}

1
lrcview/.gitignore vendored
View File

@ -1 +0,0 @@
/build

View File

@ -1,22 +0,0 @@
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
android {
namespace 'me.wcy.lrcview'
compileSdk 34
defaultConfig {
minSdkVersion 23
//noinspection ExpiredTargetSdkVersion
targetSdk 31
versionCode 1
versionName "1.0"
}
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
}

View File

@ -1,5 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</manifest>

View File

@ -1,117 +0,0 @@
/*
* Copyright (C) 2017 wangchenyan
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package me.wcy.lrcview;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
/**
* 一行歌词实体
*/
public class LrcEntry implements Comparable<LrcEntry> {
public long time;
public String text, secondText;
private StaticLayout staticLayout;
/**
* 歌词距离视图顶部的距离
*/
private float offset = Float.MIN_VALUE;
public static final int GRAVITY_CENTER = 0;
public static final int GRAVITY_LEFT = 1;
public static final int GRAVITY_RIGHT = 2;
LrcEntry(long time, String text) {
this.time = time;
this.text = text;
}
LrcEntry(long time, String text, String secondText) {
this.time = time;
this.text = text;
this.secondText = secondText;
}
void init(TextPaint paint, int width, int gravity) {
Layout.Alignment align;
switch (gravity) {
case GRAVITY_LEFT:
align = Layout.Alignment.ALIGN_NORMAL;
break;
default:
case GRAVITY_CENTER:
align = Layout.Alignment.ALIGN_CENTER;
break;
case GRAVITY_RIGHT:
align = Layout.Alignment.ALIGN_OPPOSITE;
break;
}
staticLayout = new StaticLayout(
getShowText(), paint, width, align, 1f, 0f, false);
offset = Float.MIN_VALUE;
}
long getTime() {
return time;
}
StaticLayout getStaticLayout() {
return staticLayout;
}
int getHeight() {
if (staticLayout == null) {
return 0;
}
return staticLayout.getHeight();
}
public float getOffset() {
return offset;
}
public void setOffset(float offset) {
this.offset = offset;
}
String getText() {
return text;
}
void setSecondText(String secondText) {
this.secondText = secondText;
}
public String getShowText() {
if (!TextUtils.isEmpty(secondText)) {
return text + "\n" + secondText;
} else {
return text;
}
}
@Override
public int compareTo(LrcEntry entry) {
if (entry == null) {
return -1;
}
return (int) (time - entry.getTime());
}
}

View File

@ -1,244 +0,0 @@
/*
* Copyright (C) 2017 wangchenyan
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package me.wcy.lrcview;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.os.Build;
import android.text.TextUtils;
import android.text.format.DateUtils;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 工具类
*/
class LrcUtils {
private static final Pattern PATTERN_LINE = Pattern.compile("((\\[\\d\\d:\\d\\d\\.\\d{2,3}\\])+)(.+)");
private static final Pattern PATTERN_TIME = Pattern.compile("\\[(\\d\\d):(\\d\\d)\\.(\\d{2,3})\\]");
/**
* 从文件解析双语歌词
*/
static List<LrcEntry> parseLrc(File[] lrcFiles) {
if (lrcFiles == null || lrcFiles.length != 2 || lrcFiles[0] == null) {
return null;
}
File mainLrcFile = lrcFiles[0];
File secondLrcFile = lrcFiles[1];
List<LrcEntry> mainEntryList = parseLrc(mainLrcFile);
List<LrcEntry> secondEntryList = parseLrc(secondLrcFile);
if (mainEntryList != null && secondEntryList != null) {
for (LrcEntry mainEntry : mainEntryList) {
for (LrcEntry secondEntry : secondEntryList) {
if (mainEntry.getTime() == secondEntry.getTime()) {
mainEntry.setSecondText(secondEntry.getText());
}
}
}
}
return mainEntryList;
}
/**
* 从文件解析歌词
*/
private static List<LrcEntry> parseLrc(File lrcFile) {
if (lrcFile == null || !lrcFile.exists()) {
return null;
}
List<LrcEntry> entryList = new ArrayList<>();
try {
@SuppressLint({"NewApi", "LocalSuppress"})
BufferedReader br = new BufferedReader(new InputStreamReader(
Files.newInputStream(lrcFile.toPath()), StandardCharsets.UTF_8));
String line;
while ((line = br.readLine()) != null) {
List<LrcEntry> list = parseLine(line);
if (list != null && !list.isEmpty()) {
entryList.addAll(list);
}
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
Collections.sort(entryList);
return entryList;
}
/**
* 从文本解析双语歌词
*/
static List<LrcEntry> parseLrc(String[] lrcTexts) {
if (lrcTexts == null || lrcTexts.length != 2 || TextUtils.isEmpty(lrcTexts[0])) {
return null;
}
String mainLrcText = lrcTexts[0];
String secondLrcText = lrcTexts[1];
List<LrcEntry> mainEntryList = parseLrc(mainLrcText);
List<LrcEntry> secondEntryList = parseLrc(secondLrcText);
if (mainEntryList != null && secondEntryList != null) {
for (LrcEntry mainEntry : mainEntryList) {
for (LrcEntry secondEntry : secondEntryList) {
if (mainEntry.getTime() == secondEntry.getTime()) {
mainEntry.setSecondText(secondEntry.getText());
}
}
}
}
return mainEntryList;
}
/**
* 从文本解析歌词
*/
private static List<LrcEntry> parseLrc(String lrcText) {
if (TextUtils.isEmpty(lrcText)) {
return null;
}
if (lrcText.startsWith("\uFEFF")) {
lrcText = lrcText.replace("\uFEFF", "");
}
List<LrcEntry> entryList = new ArrayList<>();
String[] array = lrcText.split("\\n");
for (String line : array) {
List<LrcEntry> list = parseLine(line);
if (list != null && !list.isEmpty()) {
entryList.addAll(list);
}
}
Collections.sort(entryList);
return entryList;
}
/**
* 获取网络文本需要在工作线程中执行
*/
static String getContentFromNetwork(String url, String charset) {
String lrcText = null;
try {
URL _url = new URL(url);
HttpURLConnection conn = (HttpURLConnection) _url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
if (conn.getResponseCode() == 200) {
InputStream is = conn.getInputStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
is.close();
bos.close();
lrcText = bos.toString(charset);
}
} catch (Exception e) {
e.printStackTrace();
}
return lrcText;
}
/**
* 解析一行歌词
*/
private static List<LrcEntry> parseLine(String line) {
if (TextUtils.isEmpty(line)) {
return null;
}
line = line.trim();
// [00:17.65]让我掉下眼泪的
Matcher lineMatcher = PATTERN_LINE.matcher(line);
if (!lineMatcher.matches()) {
return null;
}
String times = lineMatcher.group(1);
String text = lineMatcher.group(3);
List<LrcEntry> entryList = new ArrayList<>();
// [00:17.65]
Matcher timeMatcher = PATTERN_TIME.matcher(times);
while (timeMatcher.find()) {
long min = Long.parseLong(timeMatcher.group(1));
long sec = Long.parseLong(timeMatcher.group(2));
String milString = timeMatcher.group(3);
long mil = Long.parseLong(milString);
// 如果毫秒是两位数需要乘以10
if (milString.length() == 2) {
mil = mil * 10;
}
long time = min * DateUtils.MINUTE_IN_MILLIS + sec * DateUtils.SECOND_IN_MILLIS + mil;
entryList.add(new LrcEntry(time, text));
}
return entryList;
}
/**
* 转为[:]
*/
static String formatTime(long milli) {
int m = (int) (milli / DateUtils.MINUTE_IN_MILLIS);
int s = (int) ((milli / DateUtils.SECOND_IN_MILLIS) % 60);
String mm = String.format(Locale.getDefault(), "%02d", m);
String ss = String.format(Locale.getDefault(), "%02d", s);
return mm + ":" + ss;
}
/**
* 强制开启动画
* Android 10 以后无法使用
*/
static void resetDurationScale() {
try {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
@SuppressLint("DiscouragedPrivateApi")
Field mField = ValueAnimator.class.getDeclaredField("sDurationScale");
mField.setAccessible(true);
mField.setFloat(null, 1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -1,841 +0,0 @@
/*
* Copyright (C) 2017 wangchenyan
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package me.wcy.lrcview;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Looper;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.Scroller;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* 歌词
* Created by wcy on 2015/11/9.
*
* @noinspection unused
*/
@SuppressLint("StaticFieldLeak")
public class LrcView extends View {
private static final String TAG = "LrcView";
private static final long ADJUST_DURATION = 100;
private static final long TIMELINE_KEEP_TIME = 4 * DateUtils.SECOND_IN_MILLIS;
public static List<LrcEntry> mLrcEntryList = new ArrayList<>();
private TextPaint mLrcPaint = new TextPaint(), mTimePaint = new TextPaint();
private Paint.FontMetrics mTimeFontMetrics;
private Drawable mPlayDrawable;
private float mDividerHeight;
private long mAnimationDuration;
private int mNormalTextColor;
private float mNormalTextSize;
private int mCurrentTextColor;
private float mCurrentTextSize;
private int mTimelineTextColor;
private int mTimelineColor;
private int mTimeTextColor;
private int mDrawableWidth;
private int mTimeTextWidth;
private String mDefaultLabel;
private float mLrcPadding;
private OnPlayClickListener mOnPlayClickListener;
private OnTapListener mOnTapListener;
private ValueAnimator mAnimator;
private GestureDetector mGestureDetector;
private Scroller mScroller;
private float mOffset;
private int mCurrentLine;
private Object mFlag;
private boolean isShowTimeline;
private boolean isTouching;
private boolean isFling;
/**
* 歌词显示位置靠左/居中/靠右
*/
private int mTextGravity;
/**
* 播放按钮点击监听器点击后应该跳转到指定播放位置
*/
public interface OnPlayClickListener {
/**
* 播放按钮被点击应该跳转到指定播放位置
*
* @param view 歌词控件
* @param time 选中播放进度
* @return 是否成功消费该事件如果成功消费则会更新UI
*/
boolean onPlayClick(LrcView view, long time);
}
/**
* 歌词控件点击监听器
*/
public interface OnTapListener {
/**
* 歌词控件被点击
*
* @param view 歌词控件
* @param x 点击坐标x相对于控件
* @param y 点击坐标y相对于控件
*/
void onTap(LrcView view, float x, float y);
}
public LrcView(Context context) {
this(context, null);
init(null);
}
public LrcView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
init(attrs);
}
public LrcView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
private void init(AttributeSet attrs) {
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.LrcView);
mCurrentTextSize = ta.getDimension(R.styleable.LrcView_lrcTextSize,
getResources().getDimension(R.dimen.lrc_text_size));
mNormalTextSize = ta.getDimension(R.styleable.LrcView_lrcNormalTextSize,
getResources().getDimension(R.dimen.lrcNormalTextSize));
if (mNormalTextSize == 0) {
mNormalTextSize = mCurrentTextSize;
}
mDividerHeight = ta.getDimension(R.styleable.LrcView_lrcDividerHeight, getResources().getDimension(R.dimen.lrc_divider_height));
int defDuration = getResources().getInteger(R.integer.lrc_animation_duration);
mAnimationDuration = ta.getInt(R.styleable.LrcView_lrcAnimationDuration, defDuration);
mAnimationDuration = (mAnimationDuration < 0) ? defDuration : mAnimationDuration;
mNormalTextColor = ta.getColor(R.styleable.LrcView_lrcNormalTextColor,
ContextCompat.getColor(getContext(), R.color.lrc_normal_text_color));
mCurrentTextColor = ta.getColor(R.styleable.LrcView_lrcCurrentTextColor,
ContextCompat.getColor(getContext(), R.color.lrc_current_text_color));
mTimelineTextColor = ta.getColor(R.styleable.LrcView_lrcTimelineTextColor,
ContextCompat.getColor(getContext(), R.color.lrc_timeline_text_color));
mDefaultLabel = ta.getString(R.styleable.LrcView_lrcLabel);
mDefaultLabel = TextUtils.isEmpty(mDefaultLabel) ? getContext().getString(R.string.lrc_label) : mDefaultLabel;
mLrcPadding = ta.getDimension(R.styleable.LrcView_lrcPadding, 0);
mTimelineColor = ta.getColor(R.styleable.LrcView_lrcTimelineColor,
ContextCompat.getColor(getContext(), R.color.lrc_timeline_color));
float timelineHeight = ta.getDimension(R.styleable.LrcView_lrcTimelineHeight, getResources().getDimension(R.dimen.lrc_timeline_height));
mPlayDrawable = ta.getDrawable(R.styleable.LrcView_lrcPlayDrawable);
mPlayDrawable = (mPlayDrawable == null) ?
ContextCompat.getDrawable(getContext(), R.drawable.lrc_play) : mPlayDrawable;
mTimeTextColor = ta.getColor(R.styleable.LrcView_lrcTimeTextColor,
ContextCompat.getColor(getContext(), R.color.lrc_time_text_color));
float timeTextSize = ta.getDimension(R.styleable.LrcView_lrcTimeTextSize, getResources().getDimension(R.dimen.lrc_time_text_size));
mTextGravity = ta.getInteger(R.styleable.LrcView_lrcTextGravity, LrcEntry.GRAVITY_CENTER);
ta.recycle();
mDrawableWidth = (int) getResources().getDimension(R.dimen.lrc_drawable_width);
mTimeTextWidth = (int) getResources().getDimension(R.dimen.lrc_time_width);
mLrcPaint.setAntiAlias(true);
mLrcPaint.setTextSize(mCurrentTextSize);
mLrcPaint.setTextAlign(Paint.Align.LEFT);
mTimePaint.setAntiAlias(true);
mTimePaint.setTextSize(timeTextSize);
mTimePaint.setTextAlign(Paint.Align.CENTER);
//noinspection SuspiciousNameCombination
mTimePaint.setStrokeWidth(timelineHeight);
mTimePaint.setStrokeCap(Paint.Cap.ROUND);
mTimeFontMetrics = mTimePaint.getFontMetrics();
mGestureDetector = new GestureDetector(getContext(), mSimpleOnGestureListener);
mGestureDetector.setIsLongpressEnabled(false);
mScroller = new Scroller(getContext());
}
/**
* 设置非当前行歌词字体颜色
*/
public void setNormalColor(int normalColor) {
mNormalTextColor = normalColor;
postInvalidate();
}
/**
* 普通歌词文本字体大小
*/
public void setNormalTextSize(float size) {
mNormalTextSize = size;
}
/**
* 当前歌词文本字体大小
*/
public void setCurrentTextSize(float size) {
mCurrentTextSize = size;
}
/**
* 设置当前行歌词的字体颜色
*/
public void setCurrentColor(int currentColor) {
mCurrentTextColor = currentColor;
postInvalidate();
}
/**
* 设置拖动歌词时选中歌词的字体颜色
*/
public void setTimelineTextColor(int timelineTextColor) {
mTimelineTextColor = timelineTextColor;
postInvalidate();
}
/**
* 设置拖动歌词时时间线的颜色
*/
public void setTimelineColor(int timelineColor) {
mTimelineColor = timelineColor;
postInvalidate();
}
/**
* 设置拖动歌词时右侧时间字体颜色
*/
public void setTimeTextColor(int timeTextColor) {
mTimeTextColor = timeTextColor;
postInvalidate();
}
/**
* 设置歌词是否允许拖动
*
* @param draggable 是否允许拖动
* @param onPlayClickListener 设置歌词拖动后播放按钮点击监听器如果允许拖动则不能为 null
*/
public void setDraggable(boolean draggable, OnPlayClickListener onPlayClickListener) {
if (draggable) {
if (onPlayClickListener == null) {
throw new IllegalArgumentException("if draggable == true, onPlayClickListener must not be null");
}
mOnPlayClickListener = onPlayClickListener;
} else {
mOnPlayClickListener = null;
}
}
/**
* 设置播放按钮点击监听器
*
* @param onPlayClickListener 如果为非 null 则激活歌词拖动功能否则将将禁用歌词拖动功能
* @deprecated use {@link #setDraggable(boolean, OnPlayClickListener)} instead
*/
@Deprecated
public void setOnPlayClickListener(OnPlayClickListener onPlayClickListener) {
mOnPlayClickListener = onPlayClickListener;
}
/**
* 设置歌词控件点击监听器
*
* @param onTapListener 歌词控件点击监听器
*/
public void setOnTapListener(OnTapListener onTapListener) {
mOnTapListener = onTapListener;
}
/**
* 设置歌词为空时屏幕中央显示的文字暂无歌词
*/
public void setLabel(String label) {
runOnUi(() -> {
mDefaultLabel = label;
invalidate();
});
}
/**
* 加载歌词文件
*
* @param lrcFile 歌词文件
*/
public void loadLrc(File lrcFile) {
loadLrc(lrcFile, null);
}
/**
* 加载双语歌词文件两种语言的歌词时间戳需要一致
*
* @param mainLrcFile 第一种语言歌词文件
* @param secondLrcFile 第二种语言歌词文件
*/
public void loadLrc(File mainLrcFile, File secondLrcFile) {
runOnUi(() -> {
reset();
StringBuilder sb = new StringBuilder("file://");
sb.append(mainLrcFile.getPath());
if (secondLrcFile != null) {
sb.append("#").append(secondLrcFile.getPath());
}
String flag = sb.toString();
setFlag(flag);
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<List<LrcEntry>> callable = () -> LrcUtils.parseLrc(new File[]{mainLrcFile, secondLrcFile});
Future<List<LrcEntry>> future = executor.submit(callable);
try {
List<LrcEntry> lrcEntries = future.get();
if (getFlag() == flag) {
onLrcLoaded(lrcEntries);
setFlag(null);
}
} catch (InterruptedException e) {
// 处理中断异常
e.printStackTrace();
} catch (ExecutionException e) {
// 处理执行异常
e.printStackTrace();
}
// 关闭线程池
executor.shutdown();
});
}
/**
* 加载歌词文本
*
* @param lrcText 歌词文本
*/
public void loadLrc(String lrcText) {
loadLrc(lrcText, null);
}
/**
* 加载双语歌词文本两种语言的歌词时间戳需要一致
*
* @param mainLrcText 第一种语言歌词文本
* @param secondLrcText 第二种语言歌词文本
*/
public void loadLrc(String mainLrcText, String secondLrcText) {
runOnUi(() -> {
reset();
StringBuilder sb = new StringBuilder("file://");
sb.append(mainLrcText);
if (secondLrcText != null) {
sb.append("#").append(secondLrcText);
}
String flag = sb.toString();
setFlag(flag);
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<List<LrcEntry>> callable = () -> LrcUtils.parseLrc(
new String[]{mainLrcText, secondLrcText});
Future<List<LrcEntry>> future = executor.submit(callable);
try {
List<LrcEntry> lrcEntries = future.get();
if (getFlag() == flag) {
onLrcLoaded(lrcEntries);
setFlag(null);
}
} catch (InterruptedException e) {
// 处理中断异常
e.printStackTrace();
} catch (ExecutionException e) {
// 处理执行异常
e.printStackTrace();
}
// 关闭线程池
executor.shutdown();
});
}
public static void Lrc(String mainLrcText, String secondLrcText) {
StringBuilder sb = new StringBuilder("file://");
sb.append(mainLrcText);
if (secondLrcText != null) {
sb.append("#").append(secondLrcText);
}
String flag = sb.toString();
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<List<LrcEntry>> callable = () -> LrcUtils.parseLrc(
new String[]{mainLrcText, secondLrcText});
Future<List<LrcEntry>> future = executor.submit(callable);
try {
mLrcEntryList = future.get();
} catch (InterruptedException e) {
// 处理中断异常
e.printStackTrace();
} catch (ExecutionException e) {
// 处理执行异常
e.printStackTrace();
}
// 关闭线程池
executor.shutdown();
}
/**
* 歌词是否有效
*
* @return true如果歌词有效否则false
*/
public boolean hasLrc() {
return !mLrcEntryList.isEmpty();
}
/**
* 刷新歌词
* time 当前播放时间
*/
public int index = 0;
public void updateTime(long time) {
if (mOnPlayClickListener == null) {
runOnUi(() -> {
if (!hasLrc()) {
return;
}
index = findShowLine(time);
invalidate();
});
return;
}
runOnUi(() -> {
if (!hasLrc()) {
return;
}
int line = findShowLine(time);
if (line != mCurrentLine) {
mCurrentLine = line;
if (!isShowTimeline) {
smoothScrollTo(line);
} else {
invalidate();
}
}
});
}
/**
* 将歌词滚动到指定时间
*
* @param time 指定的时间
* @deprecated 请使用 {@link #updateTime(long)} 代替
*/
@Deprecated
public void onDrag(long time) {
updateTime(time);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
initPlayDrawable();
initEntryList();
if (hasLrc()) {
smoothScrollTo(mCurrentLine, 0L);
}
}
}
@Override
protected void onDraw(@NonNull Canvas canvas) {
super.onDraw(canvas);
int centerY = getHeight() / 2;
// 无歌词文件
if (!hasLrc()) {
mLrcPaint.setColor(mCurrentTextColor);
@SuppressLint("DrawAllocation")
StaticLayout staticLayout = new StaticLayout(mDefaultLabel, mLrcPaint,
(int) getLrcWidth(), Layout.Alignment.ALIGN_CENTER, 1f, 0f, false);
drawText(canvas, staticLayout, centerY);
return;
}
if (mOnPlayClickListener == null) {
mLrcPaint.setColor(mCurrentTextColor);
@SuppressLint("DrawAllocation")
StaticLayout staticLayout = new StaticLayout(mLrcEntryList.get(index).getShowText()
, mLrcPaint,
(int) getLrcWidth(), Layout.Alignment.ALIGN_CENTER, 1f,
0f, false);
drawText(canvas, staticLayout, centerY);
return;
}
int centerLine = getCenterLine();
if (isShowTimeline) {
mPlayDrawable.draw(canvas);
mTimePaint.setColor(mTimelineColor);
canvas.drawLine(mTimeTextWidth, centerY, getWidth() - mTimeTextWidth, centerY, mTimePaint);
mTimePaint.setColor(mTimeTextColor);
String timeText = LrcUtils.formatTime(mLrcEntryList.get(centerLine).getTime());
float timeX = getWidth() - (float) mTimeTextWidth / 2;
float timeY = centerY - (mTimeFontMetrics.descent + mTimeFontMetrics.ascent) / 2;
canvas.drawText(timeText, timeX, timeY, mTimePaint);
}
canvas.translate(0, mOffset);
float y = 0;
for (int i = 0; i < mLrcEntryList.size(); i++) {
if (i > 0) {
y += ((mLrcEntryList.get(i - 1).getHeight() + mLrcEntryList.get(i).getHeight()) >> 1)
+ mDividerHeight;
}
if (i == mCurrentLine) {
mLrcPaint.setTextSize(mCurrentTextSize);
mLrcPaint.setColor(mCurrentTextColor);
} else if (isShowTimeline && i == centerLine) {
mLrcPaint.setColor(mTimelineTextColor);
} else {
mLrcPaint.setTextSize(mNormalTextSize);
mLrcPaint.setColor(mNormalTextColor);
}
drawText(canvas, mLrcEntryList.get(i).getStaticLayout(), y);
}
}
/**
* 画一行歌词
*
* @param y 歌词中心 Y 坐标
*/
private void drawText(Canvas canvas, StaticLayout staticLayout, float y) {
if (staticLayout != null) {
canvas.save();
canvas.translate(mLrcPadding, y - (staticLayout.getHeight() >> 1));
staticLayout.draw(canvas);
canvas.restore();
}
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
isTouching = false;
// 手指离开屏幕启动延时任务恢复歌词位置
if (hasLrc() && isShowTimeline) {
adjustCenter();
postDelayed(hideTimelineRunnable, TIMELINE_KEEP_TIME);
}
}
return mGestureDetector.onTouchEvent(event);
}
/**
* 手势监听器
*/
private GestureDetector.SimpleOnGestureListener mSimpleOnGestureListener =
new GestureDetector.SimpleOnGestureListener() {
// 本次点击仅仅为了停止歌词滚动则不响应点击事件
private boolean isTouchForStopFling = false;
@Override
public boolean onDown(@NonNull MotionEvent e) {
if (!hasLrc()) {
return mOnTapListener != null;
}
isTouching = true;
removeCallbacks(hideTimelineRunnable);
if (isFling) {
isTouchForStopFling = true;
mScroller.forceFinished(true);
} else {
isTouchForStopFling = false;
}
return mOnPlayClickListener != null || mOnTapListener != null;
}
@Override
public boolean onScroll(MotionEvent e1, @NonNull MotionEvent e2, float distanceX, float distanceY) {
if (!hasLrc() || mOnPlayClickListener == null) {
return super.onScroll(e1, e2, distanceX, distanceY);
}
if (!isShowTimeline) {
isShowTimeline = true;
} else {
mOffset -= distanceY;
mOffset = Math.min(mOffset, getOffset(0));
mOffset = Math.max(mOffset, getOffset(mLrcEntryList.size() - 1));
}
invalidate();
return true;
}
@Override
public boolean onFling(MotionEvent e1, @NonNull MotionEvent e2, float velocityX, float velocityY) {
if (!hasLrc() || mOnPlayClickListener == null) {
return super.onFling(e1, e2, velocityX, velocityY);
}
if (isShowTimeline) {
isFling = true;
removeCallbacks(hideTimelineRunnable);
mScroller.fling(0, (int) mOffset, 0, (int) velocityY, 0, 0, (int) getOffset(mLrcEntryList.size() - 1), (int) getOffset(0));
return true;
}
return super.onFling(e1, e2, velocityX, velocityY);
}
@Override
public boolean onSingleTapConfirmed(@NonNull MotionEvent e) {
if (hasLrc() && mOnPlayClickListener != null && isShowTimeline && mPlayDrawable.getBounds().contains((int) e.getX(), (int) e.getY())) {
int centerLine = getCenterLine();
long centerLineTime = mLrcEntryList.get(centerLine).getTime();
// onPlayClick 消费了才更新 UI
if (mOnPlayClickListener != null && mOnPlayClickListener.onPlayClick(LrcView.this, centerLineTime)) {
isShowTimeline = false;
removeCallbacks(hideTimelineRunnable);
mCurrentLine = centerLine;
invalidate();
return true;
}
} else if (mOnTapListener != null && !isTouchForStopFling) {
mOnTapListener.onTap(LrcView.this, e.getX(), e.getY());
}
return super.onSingleTapConfirmed(e);
}
};
private Runnable hideTimelineRunnable = new Runnable() {
@Override
public void run() {
Log.d(TAG, "hideTimelineRunnable run");
if (hasLrc() && isShowTimeline) {
isShowTimeline = false;
smoothScrollTo(mCurrentLine);
}
}
};
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
mOffset = mScroller.getCurrY();
invalidate();
}
if (isFling && mScroller.isFinished()) {
Log.d(TAG, "fling finish");
isFling = false;
if (hasLrc() && !isTouching) {
adjustCenter();
postDelayed(hideTimelineRunnable, TIMELINE_KEEP_TIME);
}
}
}
@Override
protected void onDetachedFromWindow() {
removeCallbacks(hideTimelineRunnable);
super.onDetachedFromWindow();
}
private void onLrcLoaded(List<LrcEntry> entryList) {
if (entryList != null && !entryList.isEmpty()) {
mLrcEntryList.addAll(entryList);
}
Collections.sort(mLrcEntryList);
initEntryList();
invalidate();
}
private void initPlayDrawable() {
int l = (mTimeTextWidth - mDrawableWidth) / 2;
int t = getHeight() / 2 - mDrawableWidth / 2;
int r = l + mDrawableWidth;
int b = t + mDrawableWidth;
mPlayDrawable.setBounds(l, t, r, b);
}
private void initEntryList() {
if (!hasLrc() || getWidth() == 0) {
return;
}
for (LrcEntry lrcEntry : mLrcEntryList) {
lrcEntry.init(mLrcPaint, (int) getLrcWidth(), mTextGravity);
}
mOffset = (float) getHeight() / 2;
}
private void reset() {
endAnimation();
mScroller.forceFinished(true);
isShowTimeline = false;
isTouching = false;
isFling = false;
removeCallbacks(hideTimelineRunnable);
mLrcEntryList.clear();
mOffset = 0;
mCurrentLine = 0;
invalidate();
}
/**
* 将中心行微调至正中心
*/
private void adjustCenter() {
smoothScrollTo(getCenterLine(), ADJUST_DURATION);
}
/**
* 滚动到某一行
*/
private void smoothScrollTo(int line) {
smoothScrollTo(line, mAnimationDuration);
}
/**
* 滚动到某一行
*/
private void smoothScrollTo(int line, long duration) {
float offset = getOffset(line);
endAnimation();
mAnimator = ValueAnimator.ofFloat(mOffset, offset);
mAnimator.setDuration(duration);
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.addUpdateListener(animation -> {
mOffset = (float) animation.getAnimatedValue();
invalidate();
});
LrcUtils.resetDurationScale();
mAnimator.start();
}
/**
* 结束滚动动画
*/
private void endAnimation() {
if (mAnimator != null && mAnimator.isRunning()) {
mAnimator.end();
}
}
/**
* 二分法查找当前时间应该显示的行数最后一个 <= time 的行数
*/
private int findShowLine(long time) {
int left = 0;
int right = mLrcEntryList.size();
while (left <= right) {
int middle = (left + right) / 2;
long middleTime = mLrcEntryList.get(middle).getTime();
if (time < middleTime) {
right = middle - 1;
} else {
if (middle + 1 >= mLrcEntryList.size() || time < mLrcEntryList.get(middle + 1).getTime()) {
return middle;
}
left = middle + 1;
}
}
return 0;
}
/**
* 获取当前在视图中央的行数
*/
private int getCenterLine() {
int centerLine = 0;
float minDistance = Float.MAX_VALUE;
for (int i = 0; i < mLrcEntryList.size(); i++) {
if (Math.abs(mOffset - getOffset(i)) < minDistance) {
minDistance = Math.abs(mOffset - getOffset(i));
centerLine = i;
}
}
return centerLine;
}
/**
* 获取歌词距离视图顶部的距离
* 采用懒加载方式
*/
private float getOffset(int line) {
if (mLrcEntryList.get(line).getOffset() == Float.MIN_VALUE) {
float offset = (float) getHeight() / 2;
for (int i = 1; i <= line; i++) {
offset -= ((mLrcEntryList.get(i - 1).getHeight() + mLrcEntryList.get(i).getHeight()) >> 1) + mDividerHeight;
}
mLrcEntryList.get(line).setOffset(offset);
}
return mLrcEntryList.get(line).getOffset();
}
/**
* 获取歌词宽度
*/
private float getLrcWidth() {
return getWidth() - mLrcPadding * 2;
}
/**
* 在主线程中运行
*/
private void runOnUi(Runnable r) {
if (Looper.myLooper() == Looper.getMainLooper()) {
r.run();
} else {
post(r);
}
}
private Object getFlag() {
return mFlag;
}
private void setFlag(Object flag) {
this.mFlag = flag;
}
}

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="LrcView">
<attr name="lrcTextSize" format="dimension" />
<attr name="lrcNormalTextSize" format="dimension" />
<attr name="lrcDividerHeight" format="dimension" />
<attr name="lrcNormalTextColor" format="reference|color" />
<attr name="lrcCurrentTextColor" format="reference|color" />
<attr name="lrcTimelineTextColor" format="reference|color" />
<attr name="lrcAnimationDuration" format="integer" />
<attr name="lrcLabel" format="string" />
<attr name="lrcPadding" format="dimension" />
<attr name="lrcTimelineColor" format="reference|color" />
<attr name="lrcTimelineHeight" format="dimension" />
<attr name="lrcPlayDrawable" format="reference" />
<attr name="lrcTimeTextColor" format="reference|color" />
<attr name="lrcTimeTextSize" format="dimension" />
<attr name="lrcTextGravity">
<enum name="center" value="0" />
<enum name="left" value="1" />
<enum name="right" value="2" />
</attr>
</declare-styleable>
</resources>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="lrc_normal_text_color">#9E9E9E</color>
<color name="lrc_current_text_color">#FF4081</color>
<color name="lrc_timeline_text_color">#F8BBD0</color>
<color name="lrc_timeline_color">#809E9E9E</color>
<color name="lrc_time_text_color">#809E9E9E</color>
</resources>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="lrc_animation_duration">1000</integer>
<dimen name="lrc_text_size">20sp</dimen>
<dimen name="lrcNormalTextSize">16sp</dimen>
<dimen name="lrc_time_text_size">12sp</dimen>
<dimen name="lrc_divider_height">16dp</dimen>
<dimen name="lrc_timeline_height">1dp</dimen>
<dimen name="lrc_drawable_width">30dp</dimen>
<dimen name="lrc_time_width">40dp</dimen>
</resources>

View File

@ -1,3 +0,0 @@
<resources>
<string name="lrc_label">暂无歌词</string>
</resources>

View File

@ -17,4 +17,4 @@ dependencyResolutionManagement {
rootProject.name = "Cloud_music"
include ':app'
include(':StatusBarUtil')
include(":lrcview")
//include(":lrcview")