diff --git a/app/build.gradle.kts b/app/build.gradle.kts index be3cce7..ab91825 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -57,8 +57,13 @@ dependencies { implementation("com.github.bumptech.glide:glide:4.16.0") + + //提取图片主色 implementation ("androidx.palette:palette:1.0.0") + //动画 + implementation ("com.airbnb.android:lottie:5.2.0") + //----------media3 implementation("androidx.media3:media3-exoplayer:1.4.1") implementation("androidx.media3:media3-exoplayer-dash:1.4.1") diff --git a/app/src/main/assets/music_bounce.json b/app/src/main/assets/music_bounce.json new file mode 100644 index 0000000..e5fee43 --- /dev/null +++ b/app/src/main/assets/music_bounce.json @@ -0,0 +1,51 @@ +{ + "v": "5.5.7", + "fr": 60, + "ip": 0, + "op": 90, + "w": 500, + "h": 500, + "nm": "Audio Wave", + "ddd": 0, + "assets": [], + "layers": [ + { + "ddd": 0, + "ind": 1, + "ty": 4, + "nm": "Wave Layer", + "sr": 1, + "ks": { + "o": { "a": 0, "k": 100, "ix": 11 }, + "r": { "a": 0, "k": 0, "ix": 10 }, + "p": { "a": 0, "k": [250, 250, 0], "ix": 2 }, + "a": { "a": 0, "k": [0, 0, 0], "ix": 1 }, + "s": { + "a": 1, + "k": [ + { "i": { "x": [0.667], "y": [1] }, "o": { "x": [0.333], "y": [0] }, "t": 0, "s": [100, 100, 100] }, + { "i": { "x": [0.667], "y": [1] }, "o": { "x": [0.333], "y": [0] }, "t": 45, "s": [100, 150, 100] }, + { "t": 90, "s": [100, 100, 100] } + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "rc", + "d": 1, + "s": { "a": 0, "k": [100, 300], "ix": 2 }, + "p": { "a": 0, "k": [0, 0], "ix": 3 }, + "nm": "Rectangle Path 1", + "mn": "ADBE Vector Shape - Rect", + "hd": false + } + ], + "ip": 0, + "op": 90, + "st": 0, + "bm": 0 + } + ] +} diff --git a/app/src/main/java/com/hi/music/player/MusicApplication.java b/app/src/main/java/com/hi/music/player/MusicApplication.java index 5e351fe..0670d8e 100644 --- a/app/src/main/java/com/hi/music/player/MusicApplication.java +++ b/app/src/main/java/com/hi/music/player/MusicApplication.java @@ -9,13 +9,11 @@ import com.hi.music.player.media3.MyMediaControllerManager; public class MusicApplication extends Application { -// private final static MusicApplication sInstance = new MusicApplication(); + public static Context myApplication; -// public static MusicApplication getInstance() { -// return sInstance; -// } + diff --git a/app/src/main/java/com/hi/music/player/adapter/AdapterPlayList.java b/app/src/main/java/com/hi/music/player/adapter/AdapterPlayList.java new file mode 100644 index 0000000..926d7f6 --- /dev/null +++ b/app/src/main/java/com/hi/music/player/adapter/AdapterPlayList.java @@ -0,0 +1,59 @@ +package com.hi.music.player.adapter; + +import static androidx.media3.session.legacy.MediaControllerCompat.getMediaController; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.media3.common.MediaItem; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.bumptech.glide.request.RequestOptions; +import com.hi.music.player.MusicApplication; +import com.hi.music.player.R; +import com.hi.music.player.databinding.ItemPlayListBinding; +import com.hi.music.player.helper.CommonUtils; +import com.hi.music.player.javabean.response.ResponsePlayListInfo; +import com.hi.music.player.media3.MyMediaControllerManager; + +public class AdapterPlayList extends BaseAdapter { + @Override + protected ItemPlayListBinding getViewBinding(ViewGroup parent) { + return ItemPlayListBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); + } + + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + ResponsePlayListInfo listInfo = data.get(position); + VHolder itemHolder = (VHolder) holder; + ItemPlayListBinding vb = itemHolder.getVb(); + Glide.with(MusicApplication.myApplication) + .asDrawable() + .apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10)))) + .load(listInfo.getSmallCovert()) + .placeholder(R.mipmap.ic_launcher) + .into(vb.imCovert); + vb.songName.setText(listInfo.getSongTitle()); + vb.artistName.setText(listInfo.getSingerName()); + MyMediaControllerManager instance = MyMediaControllerManager.getInstance(); + MediaItem currentMediaItem = instance.getMediaController().getCurrentMediaItem(); + if (currentMediaItem != null && currentMediaItem.mediaId.equals(listInfo.getVideoId())) { + vb.lottieAnimationView.setVisibility(View.VISIBLE); + if (instance.getMediaController().isPlaying()) { + vb.lottieAnimationView.playAnimation(); + CommonUtils.LogMsg("-------playAnimation"); + } else { + vb.lottieAnimationView.pauseAnimation(); + CommonUtils.LogMsg("-------pauseAnimation"); + } + } else { + vb.lottieAnimationView.setVisibility(View.GONE); + CommonUtils.LogMsg("-------GONE"); + } + } +} diff --git a/app/src/main/java/com/hi/music/player/dialog/BaseDialog.java b/app/src/main/java/com/hi/music/player/dialog/BaseDialog.java index 85f9169..fd87297 100644 --- a/app/src/main/java/com/hi/music/player/dialog/BaseDialog.java +++ b/app/src/main/java/com/hi/music/player/dialog/BaseDialog.java @@ -1,7 +1,9 @@ package com.hi.music.player.dialog; +import android.annotation.SuppressLint; import android.app.Dialog; +import android.graphics.Color; import android.os.Bundle; import android.view.Gravity; import android.view.LayoutInflater; @@ -12,48 +14,80 @@ import android.view.WindowManager; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; import androidx.fragment.app.DialogFragment; import androidx.viewbinding.ViewBinding; +import com.hi.music.player.MusicApplication; +import com.hi.music.player.R; + public abstract class BaseDialog extends DialogFragment { protected T vb; - protected abstract T getViewBinding(LayoutInflater inflater, ViewGroup container); + protected abstract T getViewBinding(LayoutInflater inflater, ViewGroup container); + + protected abstract void initView(); - protected abstract void initView(); @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - vb = getViewBinding(inflater,container); + vb = getViewBinding(inflater, container); init(); initView(); return vb.getRoot(); } + @Override + public void onStart() { + super.onStart(); + } + + @SuppressLint("ResourceType") private void init() { Dialog dialog = getDialog(); setCancelable(true); + if (dialog != null) { Window window = dialog.getWindow(); if (window != null) { -// window.setBackgroundDrawableResource(); - window.getDecorView().setPadding(0, 0, 0, 0); - WindowManager.LayoutParams attributes = window.getAttributes(); - attributes.gravity = Gravity.BOTTOM; - attributes.width = WindowManager.LayoutParams.MATCH_PARENT; - attributes.height = WindowManager.LayoutParams.WRAP_CONTENT; - window.setAttributes(attributes); + if (isFullScreen()) { + window.setStatusBarColor(Color.YELLOW); // 设置状态栏为透明,或其他颜色 + // 设置 dialog 占据全屏并延伸到状态栏 +// window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); + + // 允许内容绘制到状态栏 + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + window.setBackgroundDrawableResource(R.color.color_transparent); + window.getDecorView().setPadding(0, 0, 0, 0); + WindowManager.LayoutParams attributes = window.getAttributes(); + attributes.gravity = Gravity.BOTTOM; + attributes.width = WindowManager.LayoutParams.MATCH_PARENT; + attributes.height = WindowManager.LayoutParams.MATCH_PARENT; + window.setAttributes(attributes); + } else { + window.setBackgroundDrawableResource(R.color.color_transparent); + window.getDecorView().setPadding(0, 0, 0, 0); + + WindowManager.LayoutParams attributes = window.getAttributes(); + attributes.gravity = Gravity.BOTTOM; + attributes.width = WindowManager.LayoutParams.MATCH_PARENT; + attributes.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(attributes); + } + } } } + public abstract boolean isFullScreen(); + public void closeDialog() { dismiss(); } diff --git a/app/src/main/java/com/hi/music/player/dialog/DialogPlayList.java b/app/src/main/java/com/hi/music/player/dialog/DialogPlayList.java index 3b1927c..1424d9f 100644 --- a/app/src/main/java/com/hi/music/player/dialog/DialogPlayList.java +++ b/app/src/main/java/com/hi/music/player/dialog/DialogPlayList.java @@ -1,19 +1,126 @@ package com.hi.music.player.dialog; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.net.Uri; import android.view.LayoutInflater; +import android.view.View; import android.view.ViewGroup; -import com.hi.music.player.databinding.DialogPlayListBinding; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.OptIn; +import androidx.media3.common.MediaItem; +import androidx.media3.common.util.UnstableApi; +import androidx.recyclerview.widget.LinearLayoutManager; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.Target; +import com.hi.music.player.MusicApplication; +import com.hi.music.player.R; +import com.hi.music.player.adapter.AdapterPlayList; +import com.hi.music.player.api.onImageColorListener; +import com.hi.music.player.databinding.DialogPlayListBinding; +import com.hi.music.player.helper.CommonUtils; +import com.hi.music.player.javabean.response.ResponsePlayListInfo; +import com.hi.music.player.media3.MyControllerView; +import com.hi.music.player.media3.MyMediaControllerManager; + +import java.util.List; + +public class DialogPlayList extends BaseDialog { + private MyMediaControllerManager instance; -public class DialogPlayList extends BaseDialog{ @Override protected DialogPlayListBinding getViewBinding(LayoutInflater inflater, ViewGroup container) { - return DialogPlayListBinding.inflate(inflater,container,false); + return DialogPlayListBinding.inflate(inflater, container, false); } @Override protected void initView() { + instance = MyMediaControllerManager.getInstance(); + initPlayListUi(); + + MediaItem currentMediaItem = instance.getMediaController().getCurrentMediaItem(); + if (currentMediaItem != null) { + Uri artworkUri = currentMediaItem.mediaMetadata.artworkUri; + vb.topSongName.setText(currentMediaItem.mediaMetadata.title); + vb.topSingerName.setText(currentMediaItem.mediaMetadata.artist); + + Glide.with(MusicApplication.myApplication) + .asDrawable() + .apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10)))) + .load(artworkUri) + .placeholder(R.mipmap.ic_launcher) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target target, boolean isFirstResource) { + CommonUtils.LogMsg(e.getMessage()); + return false; + } + + @OptIn(markerClass = UnstableApi.class) + @Override + public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target target, @NonNull DataSource dataSource, boolean isFirstResource) { + CommonUtils.getDominantDarkColor1(resource, new onImageColorListener() { + @Override + public void onImageColor(int color) { + if (color == -1) { + return; + } + int lighterColor = CommonUtils.adjustBrightness(color, 1.2f); // 比原始颜色亮 20% + int darkerColor = CommonUtils.adjustBrightness(color, 0.8f); // 比原始颜色暗 20% +// GradientDrawable gradientDrawable = new GradientDrawable( +// GradientDrawable.Orientation.TOP_BOTTOM, +// new int[]{lighterColor, darkerColor} // 浅到深渐变 +// ); + vb.topLayout.setBackgroundColor(darkerColor); + Drawable newDrawable = CommonUtils.getNewDrawable(lighterColor, 24f, 24f, 0, 0); + vb.listLayout.setBackground(newDrawable); + + + } + }); + + return false; + } + }) + .into(vb.topIm); + } + vb.imPlay.setSelected(instance.getMediaController().isPlaying()); + + vb.imPlay.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + vb.imPlay.setSelected(!vb.imPlay.isSelected()); + if (vb.imPlay.isSelected()) { + instance.play(); + } else { + instance.pause(); + } + } + }); + + + } + + @Override + public boolean isFullScreen() { + return true; + } + + private void initPlayListUi() { + List playList = instance.getPlayList(); + AdapterPlayList adapterPlayList = new AdapterPlayList(); + vb.recyclerList.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication)); + adapterPlayList.addData(playList); + vb.recyclerList.setAdapter(adapterPlayList); } diff --git a/app/src/main/java/com/hi/music/player/helper/CommonUtils.java b/app/src/main/java/com/hi/music/player/helper/CommonUtils.java index b3ca57c..87683cd 100644 --- a/app/src/main/java/com/hi/music/player/helper/CommonUtils.java +++ b/app/src/main/java/com/hi/music/player/helper/CommonUtils.java @@ -2,8 +2,10 @@ package com.hi.music.player.helper; import android.content.Context; import android.graphics.Bitmap; +import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.util.DisplayMetrics; import android.util.Log; import android.widget.ImageView; @@ -17,6 +19,8 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import okhttp3.ResponseBody; @@ -88,42 +92,74 @@ public class CommonUtils { return String.format("%d:%02d", minutes, seconds); // 格式化为 mm:ss } - /** - * 从图片中提取主色调 - * @param imDraw - */ - public static void extractDominantColor(Drawable imDraw, onImageColorListener listener) { - BitmapDrawable drawable = (BitmapDrawable)imDraw; - if (drawable != null) { - Bitmap bitmap = drawable.getBitmap(); - // 使用 Palette 提取颜色 - Palette.from(bitmap).generate(palette -> { - if (palette != null) { - int dominantColor = palette.getDominantColor(0); - int suitableDarkColor = getSuitableDarkColor(dominantColor); - listener.onImageColor(suitableDarkColor); + // 使用 Palette 提取深色主色调 + public static void getDominantDarkColor1(Drawable imDraw, onImageColorListener listener) { + // 异步生成 Palette + BitmapDrawable drawable = (BitmapDrawable)imDraw; + if(drawable!=null){ + Bitmap bitmap = drawable.getBitmap(); + Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() { + @Override + public void onGenerated(Palette palette) { + // 首先尝试获取深色活力色 + Palette.Swatch darkVibrantSwatch = palette.getDarkVibrantSwatch(); + + // 如果没有深色活力色,尝试获取深色柔和色 + if (darkVibrantSwatch == null) { + darkVibrantSwatch = palette.getDarkMutedSwatch(); + } + + // 如果存在深色样本,则获取其 RGB 颜色值 + if (darkVibrantSwatch != null) { + int dominantDarkColor = darkVibrantSwatch.getRgb(); + listener.onImageColor(dominantDarkColor); + String dominantColorHex = String.format("#%06X", (0xFFFFFF & dominantDarkColor)); + Log.d("Dominant Dark Color", "主色调: " + dominantColorHex); // 打印主色调 + } else { + Log.d("Dominant Dark Color", "未找到深色主色调"); + listener.onImageColor(-1); + } } }); + }else { + listener.onImageColor(-1); } + + } + + // 调整颜色的亮度,factor > 1 表示变亮,factor < 1 表示变暗 + public static int adjustBrightness(int color, float factor) { + // 将 RGB 颜色转换为 HSV + float[] hsv = new float[3]; + Color.colorToHSV(color, hsv); + + // 调整亮度(V 值) + hsv[2] = Math.min(1.0f, hsv[2] * factor); // 亮度值最多是 1.0 + + // 返回调整后的颜色(HSV 转回 RGB) + return Color.HSVToColor(hsv); } - private static int getSuitableDarkColor(int color) { - // 提取颜色的 R, G, B 值 - int r = (color >> 16) & 0xff; - int g = (color >> 8) & 0xff; - int b = color & 0xff; + public static Drawable getNewDrawable(int color,float RadiusTopLeft,float RadiusTopRight,float RadiusBottomRight,float RadiusBottomLeft){ + // 创建 GradientDrawable + GradientDrawable drawable = new GradientDrawable(); - // 计算亮度 - double luminance = 0.299 * r + 0.587 * g + 0.114 * b; + // 设置形状为矩形 + drawable.setShape(GradientDrawable.RECTANGLE); - // 如果亮度较高,则选择更深的颜色 - if (luminance > 128) { - return 0xFF000000; // 黑色 - } else { - // 如果颜色较暗,选择一种深色调 - return 0xFF1F1F1F; // 深灰色作为替代 - } + // 设置背景颜色 + drawable.setColor(color); + + // 设置顶部圆角 (top-left and top-right) + float[] radii = new float[]{ + RadiusTopLeft, RadiusTopLeft, // top-left radius + RadiusTopRight, RadiusTopRight, // top-right radius + RadiusBottomRight, RadiusBottomRight, // bottom-right radius + RadiusBottomLeft, RadiusBottomLeft // bottom-left radius + }; + drawable.setCornerRadii(radii); + return drawable; } } diff --git a/app/src/main/java/com/hi/music/player/helper/MyValue.java b/app/src/main/java/com/hi/music/player/helper/MyValue.java index 7bbe8b8..4a3360e 100644 --- a/app/src/main/java/com/hi/music/player/helper/MyValue.java +++ b/app/src/main/java/com/hi/music/player/helper/MyValue.java @@ -5,6 +5,13 @@ public class MyValue { public static String KEY_PLAY_ACTIVITY_SINGER = "click_singer"; //播放错误 - public static int PLAY_STATUS_CODE = -1; + public final static int PLAY_STATUS_CODE_ERROR = -1; + + //正在播放 + public final static int PLAY_STATUS_CODE_PLAYING = -2; + + + //暂停或者停止 + public final static int PLAY_STATUS_CODE_PAUSE = -3; //-----------------------------PlayActivity } diff --git a/app/src/main/java/com/hi/music/player/media3/MyMediaControllerManager.java b/app/src/main/java/com/hi/music/player/media3/MyMediaControllerManager.java index 9f58d9a..8225419 100644 --- a/app/src/main/java/com/hi/music/player/media3/MyMediaControllerManager.java +++ b/app/src/main/java/com/hi/music/player/media3/MyMediaControllerManager.java @@ -24,10 +24,7 @@ import com.hi.music.player.javabean.response.ResponsePlayListInfo; import com.hi.music.player.javabean.response.ResponsePlayUrl; import com.hi.music.player.network.RetrofitManager; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.Objects; import java.util.concurrent.ExecutionException; public class MyMediaControllerManager { @@ -82,7 +79,7 @@ public class MyMediaControllerManager { @Override public void onPlayerError(PlaybackException error) { CommonUtils.LogMsg("=-----PlaybackException+" + error.getMessage()); - mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE); + mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_ERROR); } @Override @@ -99,7 +96,7 @@ public class MyMediaControllerManager { public void onIsPlayingChanged(boolean isPlaying) { if (isPlaying) { - + mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PLAYING); // TODO: 2024/9/26 自动播放完成切歌到下一首播放没有触发这里请求下一首 // 播放器开始播放 MediaItem currentItem = mediaController.getCurrentMediaItem(); @@ -116,7 +113,7 @@ public class MyMediaControllerManager { } } else { // 播放器暂停或停止 - + mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PAUSE); } } @@ -185,6 +182,10 @@ public class MyMediaControllerManager { this.playList = playList; } + public List getPlayList() { + return playList; + } + public void resetPlayList(){ mediaController.clearMediaItems(); } @@ -278,7 +279,10 @@ public class MyMediaControllerManager { if (mediaController.isPlaying()) mediaController.pause(); } - + public void stop() { + if (mediaController.isPlaying()) + mediaController.stop(); + } public void playNext() { if (mediaController.hasNextMediaItem()) { mediaController.seekToNextMediaItem(); diff --git a/app/src/main/java/com/hi/music/player/network/JsonHelper.java b/app/src/main/java/com/hi/music/player/network/JsonHelper.java index 35443c9..9a2472e 100644 --- a/app/src/main/java/com/hi/music/player/network/JsonHelper.java +++ b/app/src/main/java/com/hi/music/player/network/JsonHelper.java @@ -319,7 +319,7 @@ public class JsonHelper { } JSONArray jsonArray = jsonObject.getJSONObject("thumbnail").getJSONArray("thumbnails"); int length = jsonArray.length(); - int index = 0; + int index = 3; if(maxBig){ index = length - 1; } diff --git a/app/src/main/java/com/hi/music/player/ui/activity/PlayActivity.java b/app/src/main/java/com/hi/music/player/ui/activity/PlayActivity.java index e2d6ee7..6b42c2c 100644 --- a/app/src/main/java/com/hi/music/player/ui/activity/PlayActivity.java +++ b/app/src/main/java/com/hi/music/player/ui/activity/PlayActivity.java @@ -2,9 +2,13 @@ package com.hi.music.player.ui.activity; import android.content.Intent; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.net.Uri; import android.os.Handler; import android.util.Pair; import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; import android.widget.SeekBar; import androidx.annotation.NonNull; @@ -16,6 +20,7 @@ import androidx.media3.common.MediaItem; import androidx.media3.common.MediaMetadata; import androidx.media3.common.Player; import androidx.media3.common.util.UnstableApi; +import androidx.recyclerview.widget.LinearLayoutManager; import com.bumptech.glide.Glide; import com.bumptech.glide.load.DataSource; @@ -26,9 +31,11 @@ import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.target.Target; import com.hi.music.player.MusicApplication; import com.hi.music.player.R; +import com.hi.music.player.adapter.AdapterPlayList; import com.hi.music.player.api.MediaControllerListener; import com.hi.music.player.api.onImageColorListener; import com.hi.music.player.databinding.ActivityPlayBinding; +import com.hi.music.player.dialog.DialogPlayList; import com.hi.music.player.helper.CommonUtils; import com.hi.music.player.helper.MyValue; import com.hi.music.player.javabean.CustomerUrlInfo; @@ -60,10 +67,12 @@ public class PlayActivity extends BaseActivity implements S private MyMediaControllerManager mediaControllerManager; - //请求播放列表是否成功 - private boolean requestPlayList = false; - //请求第一首歌曲url是否成功 - private boolean requestPlayUrl = false; + //播放列表ui初始化 + private boolean initPlayList = false; + + private GradientDrawable gradientDrawable; + private int lighterColor,darkerColor; + @Override protected ActivityPlayBinding getViewBinding() { @@ -85,10 +94,10 @@ public class PlayActivity extends BaseActivity implements S @Override public void onChanged(List playList) { if (playList == null) { + CommonUtils.LogMsg("---------playList = null"); return; } if (playList.size() > 0) { - requestPlayList = true; mPlayList = playList; musicInfo = playList.get(0); @@ -105,7 +114,7 @@ public class PlayActivity extends BaseActivity implements S CommonUtils.LogMsg("-------------需要马上播放这首歌曲,但是此次网络请求失败"); return; } - requestPlayUrl = true; + mCurPlayInfo = customerUrlInfo.getPlayUrl(); int second = customerUrlInfo.getPlayMusicIndex(); boolean needPlayNow = customerUrlInfo.isNeedPlayNow(); @@ -126,7 +135,19 @@ public class PlayActivity extends BaseActivity implements S private void initMediaController() { mediaControllerManager = MyMediaControllerManager.getInstance(); - mediaControllerManager.resetPlayList(); + String videoId = responseSingle.getVideoId(); + MediaItem currentMediaItem = mediaControllerManager.getMediaController().getCurrentMediaItem(); + if(currentMediaItem != null){ + if(currentMediaItem.mediaId.equals(videoId)){ + // TODO: 2024/9/27 正在播放当前歌曲,又点进来 +// mediaControllerManager.getMediaController().seekTo(0); + } + if(mediaControllerManager.getMediaController().isPlaying()){ + mediaControllerManager.stop(); + } + mediaControllerManager.resetPlayList(); + } + mediaControllerManager.addListener(new MediaControllerListener() { @Override public void onPlayStatus(int playStatus) { @@ -156,6 +177,12 @@ public class PlayActivity extends BaseActivity implements S mediaControllerManager.playNext(); break; + case MyValue.PLAY_STATUS_CODE_PAUSE: + vb.btnPlay.setSelected(false); + break; + case MyValue.PLAY_STATUS_CODE_PLAYING: + vb.btnPlay.setSelected(true); + break; } } @@ -172,6 +199,7 @@ public class PlayActivity extends BaseActivity implements S @Override public void onChangeMusic(MediaItem mediaItem) { + CommonUtils.LogMsg("111111111-------22222---"+mediaItem.mediaMetadata.title +"---id="+mediaItem.mediaId); loadInfo(mediaItem); } @@ -185,6 +213,7 @@ public class PlayActivity extends BaseActivity implements S vb.btnNext.setOnClickListener(this); vb.btnPrevious.setOnClickListener(this); vb.imBack.setOnClickListener(this); + vb.btnMusicList.setOnClickListener(this); } @@ -221,7 +250,7 @@ public class PlayActivity extends BaseActivity implements S private void loadInfo(MediaItem mediaItem) { MediaMetadata mediaMetadata = mediaItem.mediaMetadata; - CommonUtils.LogMsg("--------------加载当前播放歌曲信息 "+mediaMetadata.description); + CommonUtils.LogMsg("--------------加载当前播放歌曲信息 " + mediaMetadata.description); if (mediaMetadata.artworkUri != null) { loadCovert(mediaMetadata.artworkUri.toString()); } @@ -238,15 +267,6 @@ public class PlayActivity extends BaseActivity implements S } - - /** - * 更新音频url到播放列表 - */ - private void updateAudioUrl(ResponsePlayUrl playUrl) { -// mediaControllerManager.UpdateAudioUrl(playUrl); - } - - private void loadCovert(String url) { Glide.with(MusicApplication.myApplication) .asDrawable() @@ -263,10 +283,19 @@ public class PlayActivity extends BaseActivity implements S @OptIn(markerClass = UnstableApi.class) @Override public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target target, @NonNull DataSource dataSource, boolean isFirstResource) { - CommonUtils.extractDominantColor(resource, new onImageColorListener() { + CommonUtils.getDominantDarkColor1(resource, new onImageColorListener() { @Override public void onImageColor(int color) { - vb.rootLayout.setBackgroundColor(color); + if (color == -1) { + return; + } + lighterColor = CommonUtils.adjustBrightness(color, 1.2f); // 比原始颜色亮 20% + darkerColor = CommonUtils.adjustBrightness(color, 0.8f); // 比原始颜色暗 20% + gradientDrawable = new GradientDrawable( + GradientDrawable.Orientation.TOP_BOTTOM, + new int[]{lighterColor, darkerColor} // 浅到深渐变 + ); + vb.rootLayout.setBackground(gradientDrawable); } }); @@ -317,10 +346,94 @@ public class PlayActivity extends BaseActivity implements S mediaControllerManager.playPrevious(); } else if (v.equals(vb.imBack)) { finish(); + } else if (v.equals(vb.btnMusicList)) { + initShowPlayList(true); + } else if (v.equals(vb.layoutPlayList.imPlay)) { + vb.layoutPlayList.imPlay.setSelected(!vb.layoutPlayList.imPlay.isSelected()); + if (vb.layoutPlayList.imPlay.isSelected()) { + mediaControllerManager.play(); + } else { + mediaControllerManager.pause(); + } } } + + /** + * 控制播放列表的显示 + * + * @param show + */ + private void initShowPlayList(boolean show) { + if (show) { + Animation animation = AnimationUtils.loadAnimation(this, R.anim.slide_up); + vb.layoutPlayList.linearLayout.startAnimation(animation); + vb.layoutPlayList.linearLayout.setVisibility(View.VISIBLE); + vb.contentLayout.setVisibility(View.GONE); + + if (!initPlayList) { + List playList = mediaControllerManager.getPlayList(); + AdapterPlayList adapterPlayList = new AdapterPlayList(); + vb.layoutPlayList.recyclerList.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication)); + adapterPlayList.addData(playList); + vb.layoutPlayList.recyclerList.setAdapter(adapterPlayList); + vb.layoutPlayList.imPlay.setOnClickListener(this); + initPlayList = true; + } + + MediaItem currentMediaItem = mediaControllerManager.getMediaController().getCurrentMediaItem(); + if (currentMediaItem != null) { + Uri artworkUri = currentMediaItem.mediaMetadata.artworkUri; + vb.layoutPlayList.topSongName.setText(currentMediaItem.mediaMetadata.title); + vb.layoutPlayList.topSingerName.setText(currentMediaItem.mediaMetadata.artist); + + + vb.layoutPlayList.topLayout.setBackgroundColor(darkerColor); + GradientDrawable gradientDrawable = new GradientDrawable( + GradientDrawable.Orientation.TOP_BOTTOM, + new int[]{darkerColor, darkerColor} + ); + vb.rootLayout.setBackground(gradientDrawable); + Drawable newDrawable = CommonUtils.getNewDrawable(lighterColor, 24f, 24f, 0, 0); + vb.layoutPlayList.listLayout.setBackground(newDrawable); + + + Glide.with(MusicApplication.myApplication) + .asDrawable() + .apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10)))) + .load(artworkUri) + .placeholder(R.mipmap.ic_launcher) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target target, boolean isFirstResource) { + CommonUtils.LogMsg(e.getMessage()); + return false; + } + @OptIn(markerClass = UnstableApi.class) + @Override + public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target target, @NonNull DataSource dataSource, boolean isFirstResource) { + + return false; + } + }) + .into(vb.layoutPlayList.topIm); + } + vb.layoutPlayList.imPlay.setSelected(mediaControllerManager.getMediaController().isPlaying()); + + } else { + + vb.rootLayout.setBackground(gradientDrawable); + vb.contentLayout.setVisibility(View.VISIBLE); + + Animation animation = AnimationUtils.loadAnimation(this, R.anim.slide_down); + vb.layoutPlayList.linearLayout.startAnimation(animation); + vb.layoutPlayList.linearLayout.setVisibility(View.GONE); + } + + + } + @Override protected void onDestroy() { super.onDestroy(); @@ -328,6 +441,14 @@ public class PlayActivity extends BaseActivity implements S mHandler.removeCallbacks(mRunnable); } + @Override + public void onBackPressed() { + if (vb.layoutPlayList.linearLayout.getVisibility()==View.VISIBLE) { + initShowPlayList(false); + } else { + super.onBackPressed(); // 调用系统默认的返回行为 + } + } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { diff --git a/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/VMPlay.java b/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/VMPlay.java index 9166dd3..7179e4e 100644 --- a/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/VMPlay.java +++ b/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/VMPlay.java @@ -1,7 +1,5 @@ package com.hi.music.player.ui.activity.viewmodel; -import android.util.Pair; - import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; @@ -40,6 +38,8 @@ public class VMPlay extends ViewModel { String params = responseSingle.getParams(); String musicVideoType = responseSingle.getMusicVideoType(); + CommonUtils.LogMsg("111111111-------0000---"+responseSingle.getSongTitle() +"---id="+videoId); + RetrofitManager.getInstance().getPlayList(params, playlistId, videoId, musicVideoType, new RequestListener() { @Override @@ -54,6 +54,7 @@ public class VMPlay extends ViewModel { List responsePlayListInfos = JsonHelper.ResolvePlayListJson(jsonObject); MyMediaControllerManager.getInstance().setPlayList(responsePlayListInfos); _playList.setValue(responsePlayListInfos); + CommonUtils.LogMsg("111111111-------1111----"+responsePlayListInfos.get(0).getSongTitle() +"---id="+responsePlayListInfos.get(0).getVideoId()); getPlayUrl(responseSingle.getVideoId(),0,true); } else { _playList.setValue(null); @@ -78,6 +79,10 @@ public class VMPlay extends ViewModel { JSONObject jsonObject = CommonUtils.toJsonObject(data); if (jsonObject != null) { ResponsePlayUrl responsePlayUrl = JsonHelper.ResolvePlayUrlJson(jsonObject); + if(responsePlayUrl == null){ + // TODO: 2024/9/27 + return; + } MyMediaControllerManager.getInstance().addMusicToPlayList(responsePlayUrl,playListIndex); customerUrlInfo.setPlayUrl(responsePlayUrl); customerUrlInfo.setPlayMusicIndex(playListIndex); diff --git a/app/src/main/res/anim/slide_down.xml b/app/src/main/res/anim/slide_down.xml new file mode 100644 index 0000000..947e71c --- /dev/null +++ b/app/src/main/res/anim/slide_down.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_up.xml b/app/src/main/res/anim/slide_up.xml new file mode 100644 index 0000000..c2f373e --- /dev/null +++ b/app/src/main/res/anim/slide_up.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/drawable/rec_bg_18.xml b/app/src/main/res/drawable/rec_bg_18.xml new file mode 100644 index 0000000..d44f5db --- /dev/null +++ b/app/src/main/res/drawable/rec_bg_18.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_small_play.xml b/app/src/main/res/drawable/selector_small_play.xml new file mode 100644 index 0000000..6f8ea7d --- /dev/null +++ b/app/src/main/res/drawable/selector_small_play.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/small_pause.xml b/app/src/main/res/drawable/small_pause.xml new file mode 100644 index 0000000..c4673e8 --- /dev/null +++ b/app/src/main/res/drawable/small_pause.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/app/src/main/res/drawable/small_play.xml b/app/src/main/res/drawable/small_play.xml new file mode 100644 index 0000000..8cfeec4 --- /dev/null +++ b/app/src/main/res/drawable/small_play.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_play.xml b/app/src/main/res/layout/activity_play.xml index 702f45e..920e11f 100644 --- a/app/src/main/res/layout/activity_play.xml +++ b/app/src/main/res/layout/activity_play.xml @@ -1,103 +1,89 @@ - - - - - + android:id="@+id/content_layout" + android:layout_height="match_parent"> + + + + - + - + - + - + - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + + - \ No newline at end of file + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_play_list.xml b/app/src/main/res/layout/dialog_play_list.xml index d7fe2ec..8409438 100644 --- a/app/src/main/res/layout/dialog_play_list.xml +++ b/app/src/main/res/layout/dialog_play_list.xml @@ -1,9 +1,105 @@ - + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_play_list.xml b/app/src/main/res/layout/item_play_list.xml new file mode 100644 index 0000000..58d52c5 --- /dev/null +++ b/app/src/main/res/layout/item_play_list.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 7d5b758..1bf95d0 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -9,6 +9,7 @@ #4DFFFFFF #99FFFFFF #59FFFFFF + #1A1A1A #2D9C31 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 24be63e..f73c0a7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,4 +21,5 @@ Share Privacy Policy Terms of Service + Play next \ No newline at end of file