package com.weishitech.qichechangtingyinyue.fragment.home;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
import com.hfd.common.base.BaseFragment;
import com.hfd.common.net.GenericsCallback;
import com.hfd.common.net.HttpBuiler;
import com.hfd.common.net.JsonGenericsSerializator;
import com.hfd.common.net.Url;
import com.hfd.common.util.ToastUtil;
import com.weishitech.qichechangtingyinyue.R;
import com.weishitech.qichechangtingyinyue.bean.MusicBean;
import com.weishitech.qichechangtingyinyue.fragment.Adapter.PrivateAdapter;
import com.weishitech.qichechangtingyinyue.fragment.Adapter.QyAdapter;
import com.weishitech.qichechangtingyinyue.fragment.Adapter.SongTopAdapter;
import com.weishitech.qichechangtingyinyue.fragment.Adapter.XzAdapter;
import com.weishitech.qichechangtingyinyue.utils.DisplayUtils;
import com.weishitech.qichechangtingyinyue.utils.LeftGravitySnapHelper;
import com.weishitech.qichechangtingyinyue.utils.MusicPlayerManager;
import com.weishitech.qichechangtingyinyue.utils.OnMultiClickListener;
import com.weishitech.qichechangtingyinyue.utils.RotationAnimatorHelper;
import com.weishitech.qichechangtingyinyue.utils.ThemeManager;
import com.weishitech.qichechangtingyinyue.view.FixedSideSnapHelper;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import okhttp3.Call;
/**
* 高端语音导航首页
*/
public class HomeFragment extends BaseFragment {
// UI Views
private RecyclerView rv, sr_rv, qy_rv, xz_rv;
private ImageView iv_ss, iv_gd, sr_start, qy_start, xz_start, iv_bf;
private TextView tv_time, tv_song_name;
private LinearLayout line;
private RelativeLayout relative,relative1,relative2,relative3;
// Managers & Helpers
private MusicPlayerManager playerManager;
private ThemeManager themeManager;
private RotationAnimatorHelper rotationHelper;
private boolean isUserAuthorizedPlayback = false; // 用户是否已授权播放(点击/滑动)
private boolean isMainPlaybackActive = false; // 是否由主流程控制播放状态
// Data & State
private SongTopAdapter songTopAdapter;
private List<MusicBean.DataBean> musicDataList = new ArrayList<>();
private List<MusicBean.DataBean> privateSongList;//私人播放列表字段
private List<MusicBean.DataBean> qySongList;//轻音乐播放列表字段
private List<MusicBean.DataBean> xzSongList;//小众音乐播放列表字段
private GestureDetector gestureDetector;
@Override
protected int setLayout() {
return R.layout.fragment_home;
}
@Override
protected void initView() {
iv_ss = fvbi(R.id.iv_ss);
iv_gd = fvbi(R.id.iv_gd);
iv_bf = fvbi(R.id.iv_bf);
rv = fvbi(R.id.rv);
sr_rv = fvbi(R.id.sr_rv);
qy_rv = fvbi(R.id.qy_rv);
xz_rv = fvbi(R.id.xz_rv);
sr_start = fvbi(R.id.sr_start);
qy_start = fvbi(R.id.qy_start);
xz_start = fvbi(R.id.xz_start);
tv_time = fvbi(R.id.tv_time);
tv_song_name = fvbi(R.id.tv_song_name);
line = fvbi(R.id.line);
relative = fvbi(R.id.relative);
relative1 = fvbi(R.id.relative1);
relative2 = fvbi(R.id.relative2);
relative3 = fvbi(R.id.relative3);
// 初始化组件
playerManager = new MusicPlayerManager();
themeManager = new ThemeManager();
rotationHelper = new RotationAnimatorHelper();
// 跑马灯
tv_song_name.setEllipsize(TextUtils.TruncateAt.MARQUEE);
tv_song_name.setSingleLine(true);
tv_song_name.setSelected(true);
tv_song_name.setFocusable(true);
tv_song_name.setFocusableInTouchMode(true);
setupGestureListener(); // 滑动手势换肤
iv_bf.setImageResource(themeManager.getPlayIconRes()); // 默认显示蓝色“播放”图标
}
@Override
protected void initClick() {
// 搜索跳转
iv_ss.setOnClickListener(v -> toClass(SearchActivity.class));
// 播放/暂停按钮
iv_bf.setOnClickListener(v -> {
if (musicDataList.isEmpty()) {
ToastUtil.showShortToast("暂无歌曲可播放");
return;
}
if (playerManager.isPlaying() && isMainPlaybackActive) {
playerManager.pause();
// 如果暂停了主播放,可以视为退出主控模式(可选)
isMainPlaybackActive = false;
} else {
isMainPlaybackActive = true; // 标记为主控模式
int pos = findBestObscuredItem(rv, DisplayUtils.dp2px(requireContext(), 50f));
if (pos == RecyclerView.NO_POSITION) pos = 0;
playMusicAtPosition(pos);
}
updatePlayButtonIcon(); // 只有主控才更新 iv_bf
});
//私人音乐播放按钮点击
sr_start.setOnClickListener(v -> playPrivateFirstSong());
//轻音乐播放按钮点击
qy_start.setOnClickListener(v -> playQingyinFirstSong());
//小众音乐播放按钮点击
xz_start.setOnClickListener(v -> playXiaoZhongFirstSong());
relative1.setOnClickListener(new OnMultiClickListener() {
@Override
public void onMultiClick(View v) {
if (privateSongList == null || privateSongList.isEmpty()) {
ToastUtil.showShortToast("暂无数据");
return;
}
Bundle bundle = new Bundle();
bundle.putString("type", "私人专属好歌");
bundle.putSerializable("song_list", new ArrayList<>(privateSongList)); // 拷贝一份
toClass(MusicListActivity.class, bundle);
}
});
relative2.setOnClickListener(new OnMultiClickListener() {
@Override
public void onMultiClick(View v) {
if (qySongList == null || qySongList.isEmpty()) {
ToastUtil.showShortToast("暂无数据");
return;
}
Bundle bundle = new Bundle();
bundle.putString("type", "轻音乐");
bundle.putSerializable("song_list", new ArrayList<>(qySongList));
toClass(MusicListActivity.class, bundle);
}
});
relative3.setOnClickListener(new OnMultiClickListener() {
@Override
public void onMultiClick(View v) {
if (xzSongList == null || xzSongList.isEmpty()) {
ToastUtil.showShortToast("暂无数据");
return;
}
Bundle bundle = new Bundle();
bundle.putString("type", "小众音乐");
bundle.putSerializable("song_list", new ArrayList<>(xzSongList));
toClass(MusicListActivity.class, bundle);
}
});
}
@Override
protected void initData() {
updateTimeGreeting();
musicAppInfo();
// 设置播放器状态监听器
playerManager.setOnPlaybackStateChangedListener(new MusicPlayerManager.OnPlaybackStateChangedListener() {
@Override
public void onPlaying(int position) {
updatePlayButtonIcon();
startRotationForCurrentItem(position);
}
@Override
public void onPaused() {
updatePlayButtonIcon();
rotationHelper.stopRotation();
}
@Override
public void onCompletion() {
playNextSong();
}
@Override
public void onError(String errorMsg) {
ToastUtil.showShortToast(errorMsg);
updatePlayButtonIcon();
}
});
}
private void updateTimeGreeting() {
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
String greeting;
if (hour >= 5 && hour < 11) greeting = "HI,早上好";
else if (hour == 11 || hour == 12 || (hour >= 13 && hour < 18)) greeting = "HI,下午好";
else greeting = "HI,晚上好";
tv_time.setText(greeting);
}
private void musicAppInfo() {
HashMap<String, String> map = new HashMap<>();
showDialog();
HttpBuiler.getInfo(Url.music, map).build().execute(
new GenericsCallback<MusicBean>(new JsonGenericsSerializator()) {
@Override
public void onError(Call call, Exception e, int id) {
dissmiss();
ToastUtil.showShortToast(e.getMessage());
}
@Override
public void onResponse(MusicBean response, int id) {
dissmiss();
if ("0".equals(response.getCode()) && response.getData() != null && !response.getData().isEmpty()) {
musicDataList = response.getData();
setupMusicRecyclerView();
} else {
ToastUtil.showShortToast("暂无歌曲数据");
}
}
});
}
private void setupMusicRecyclerView() {
songTopAdapter = new SongTopAdapter();
rv.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
rv.setAdapter(songTopAdapter);
// 设置播放状态回调(用于封面旋转)
songTopAdapter.setOnPlayStateChangedListener((position, coverView) -> {
rotationHelper.stopRotation();
rotationHelper.startRotation(coverView);
});
// 必须在设置 adapter 后再初始化滚动逻辑
setupSnappingAndPlayback(rv, songTopAdapter);
// 最后设置数据
songTopAdapter.setList(musicDataList);
//私人音乐适配器
// 从第三个元素(索引=2)开始,取最多20首歌曲
int start = 2; // 第三个元素的索引
int end = Math.min(start + 20, musicDataList.size()); // 最多取20首,且不能越界
if (start >= musicDataList.size()) {
privateSongList = new ArrayList<>(); // 防止越界
ToastUtil.showShortToast("起始位置超出列表范围");
} else {
privateSongList = new ArrayList<>(musicDataList.subList(start, end));
}
PrivateAdapter privateAdapter = new PrivateAdapter();
// 设置横向 Grid 布局:每行3个
GridLayoutManager gridLayoutManager = new GridLayoutManager(requireContext(), 3, RecyclerView.HORIZONTAL, false);
sr_rv.setLayoutManager(gridLayoutManager);
sr_rv.setAdapter(privateAdapter);
privateAdapter.setList(privateSongList);
// <<< 添加吸附效果 >>>
new LeftGravitySnapHelper().attachToRecyclerView(sr_rv);
//轻音乐
// 确保 musicDataList 不为 null 且有数据
if (musicDataList == null || musicDataList.isEmpty()) {
return;
}
int qystart = 5;
int count = 6;
int qyend = Math.min(qystart + count, musicDataList.size());
qySongList = new ArrayList<>(musicDataList.subList(qystart, qyend));
QyAdapter qyAdapter = new QyAdapter();
// 设置横向 Grid 布局:每行3个
GridLayoutManager gridLayoutManagers = new GridLayoutManager(requireContext(), 2);
qy_rv.setLayoutManager(gridLayoutManagers);
qy_rv.setAdapter(qyAdapter);
qyAdapter.setList(qySongList);
//小众音乐
// 确保 musicDataList 不为 null 且有数据
if (musicDataList == null || musicDataList.isEmpty()) {
return;
}
int xzstart = 8;
int xzcount = 6;
int xzend = Math.min(xzstart + xzcount, musicDataList.size());
xzSongList = new ArrayList<>(musicDataList.subList(xzstart, xzend));
XzAdapter xzAdapter = new XzAdapter();
// 设置横向 Grid 布局:每行3个
xz_rv.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
xz_rv.setAdapter(xzAdapter);
xzAdapter.setList(xzSongList);
}
private void setupSnappingAndPlayback(RecyclerView rv, SongTopAdapter adapter) {
LinearLayoutManager layoutManager = (LinearLayoutManager) rv.getLayoutManager();
if (layoutManager == null) return;
int fixedTargetX = DisplayUtils.dp2px(requireContext(), 50f);
FixedSideSnapHelper snapHelper = new FixedSideSnapHelper(fixedTargetX);
snapHelper.attachToRecyclerView(rv);
AtomicInteger lastPlayedPosition = new AtomicInteger(RecyclerView.NO_POSITION);
final boolean[] isFirstLayoutDone = {false}; // <<< 添加标志位
// 延迟标记“首次布局已完成”
rv.post(() -> isFirstLayoutDone[0] = true);
rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
isUserAuthorizedPlayback = true;
// 🔥 关键:只有完成首次布局后才允许自动播放
if (!isFirstLayoutDone[0]) {
return;
}
int pos = findBestObscuredItem(recyclerView, fixedTargetX);
if (pos != RecyclerView.NO_POSITION && pos != lastPlayedPosition.get()) {
playMusicAtPosition(pos);
lastPlayedPosition.set(pos);
}
dispatchVisualFeedback(recyclerView, adapter);
}
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
boolean isPlayingBefore = playerManager.isPlaying();
if (newState == RecyclerView.SCROLL_STATE_DRAGGING ||
newState == RecyclerView.SCROLL_STATE_SETTLING) {
if (isPlayingBefore) {
playerManager.pause();
rotationHelper.stopRotation();
updatePlayButtonIcon();
}
}
if (newState == RecyclerView.SCROLL_STATE_IDLE && isPlayingBefore) {
playerManager.resume();
startRotationForCurrentItem(playerManager.getCurrentPlayingPosition());
updatePlayButtonIcon();
}
}
});
setupOneWayScroll(rv, requireContext());
}
private int findBestObscuredItem(RecyclerView rv, int fuzzyRightEdge) {
LinearLayoutManager lm = (LinearLayoutManager) rv.getLayoutManager();
if (lm == null) return RecyclerView.NO_POSITION;
int bestPos = RecyclerView.NO_POSITION;
float minDiff = Float.MAX_VALUE;
for (int i = 0; i < lm.getChildCount(); i++) {
View child = lm.getChildAt(i);
if (child == null) continue;
int left = lm.getDecoratedLeft(child);
int right = lm.getDecoratedRight(child);
int width = right - left;
if (right <= 0 || left >= fuzzyRightEdge) continue; // 无交集
int overlapStart = Math.max(left, 0);
int overlapEnd = Math.min(right, fuzzyRightEdge);
int overlapWidth = Math.max(0, overlapEnd - overlapStart);
float coveredRatio = (float) overlapWidth / width;
float diff = Math.abs(coveredRatio - 0.5f);
if (coveredRatio >= 0.3f && coveredRatio <= 0.7f && diff < minDiff) {
minDiff = diff;
bestPos = lm.getPosition(child);
}
}
return bestPos;
}
private void playMusicAtPosition(int position) {
if (position == RecyclerView.NO_POSITION || position >= musicDataList.size()) return;
MusicBean.DataBean bean = musicDataList.get(position);
nextSkin(); // 每次播放新歌就换主题
playerManager.play(requireContext(), position, bean.getMusic());
songTopAdapter.updatePlayingPosition(position);
tv_song_name.setText(bean.getTitle() + "-" + bean.getSinger());
ToastUtil.showShortToast("播放: " + bean.getTitle());
}
private void playNextSong() {
int nextPos = playerManager.getCurrentPlayingPosition() + 1;
if (nextPos < musicDataList.size()) {
playMusicAtPosition(nextPos);
scrollToTriggerPosition(nextPos, rv);
} else {
ToastUtil.showShortToast("已播放完全部歌曲");
}
}
private void scrollToTriggerPosition(int targetPos, RecyclerView rv) {
LinearLayoutManager lm = (LinearLayoutManager) rv.getLayoutManager();
if (lm == null) return;
LinearSmoothScroller scroller = new LinearSmoothScroller(requireContext()) {
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return lm.computeScrollVectorForPosition(targetPosition);
}
@Override
public int calculateDxToMakeVisible(View view, int snapPreference) {
int center = (lm.getDecoratedLeft(view) + lm.getDecoratedRight(view)) / 2;
int targetX = DisplayUtils.dp2px(requireContext(), 50f);
return targetX - center;
}
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return 150f / displayMetrics.densityDpi;
}
};
scroller.setTargetPosition(targetPos);
lm.startSmoothScroll(scroller);
}
private void dispatchVisualFeedback(RecyclerView rv, SongTopAdapter adapter) {
LinearLayoutManager lm = (LinearLayoutManager) rv.getLayoutManager();
if (lm == null) return;
int targetX = DisplayUtils.dp2px(requireContext(), 100f);
for (int i = 0; i < rv.getChildCount(); i++) {
View child = rv.getChildAt(i);
if (child == null) continue;
int centerX = (lm.getDecoratedLeft(child) + lm.getDecoratedRight(child)) / 2;
float distance = Math.abs(centerX - targetX);
if (distance > 600) continue;
// float alpha = 1.0f - Math.min(1.0f, distance / 300f);
// float scale = 0.8f + 0.2f * (1.0f - Math.min(1.0f, distance / 200f));
// child.setAlpha(alpha);
// child.setScaleX(scale);
// child.setScaleY(scale);
}
}
private void setupOneWayScroll(RecyclerView rv, Context context) {
final boolean[] hasScrolledLeft = {false};
final float[] startX = {0f};
rv.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(@NonNull RecyclerView recyclerView, @NonNull MotionEvent e) {
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
startX[0] = e.getX();
break;
case MotionEvent.ACTION_MOVE:
float dx = e.getX() - startX[0];
if (dx < -20 && !hasScrolledLeft[0]) {
hasScrolledLeft[0] = true;
}
if (hasScrolledLeft[0] && dx > 15) {
Toast.makeText(context, "暂只支持左滑操作", Toast.LENGTH_SHORT).show();
return true;
}
break;
}
return false;
}
});
}
private void setupGestureListener() {
gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(e2.getY() - e1.getY())) {
if (Math.abs(diffX) > 100 && Math.abs(velocityX) > 100) {
nextSkin(); // 滑动换肤
return true;
}
}
return false;
}
});
View.OnTouchListener touchListener = (v, event) -> gestureDetector.onTouchEvent(event);
line.setOnTouchListener(touchListener);
relative.setOnTouchListener(touchListener);
}
private void nextSkin() {
themeManager.nextTheme();
applyCurrentTheme();
ToastUtil.showShortToast("切换到主题 " + (themeManager.getCurrentThemeIndex() + 1));
}
private void applyCurrentTheme() {
if (!isAdded()) return; // Fragment 已 detach,不执行
boolean isPlaying = playerManager.isPlaying();
themeManager.applyThemeTo(line, relative, iv_bf, isPlaying);
}
private void updatePlayButtonIcon() {
if (!isAdded()) return;
// 如果正在播放私人歌单,则主按钮不响应
if (playerManager.isPlayingFromPrivate()) {
iv_bf.setImageResource(themeManager.getPlayIconRes());
return;
}
// 否则:根据实际播放状态更新图标
boolean isPlaying = playerManager.isPlaying();
iv_bf.setImageResource(isPlaying
? themeManager.getPauseIconRes()
: themeManager.getPlayIconRes());
}
private void startRotationForCurrentItem(int position) {
rotationHelper.stopRotation(); // 先停止任何正在进行的动画
RecyclerView.ViewHolder vh = rv.findViewHolderForAdapterPosition(position);
if (vh != null) {
ImageView coverView = vh.itemView.findViewById(R.id.iv_song_logo);
if (coverView != null) {
rotationHelper.startRotation(coverView);
}
}
}
/**
* 播放私人专属歌单的第一首歌曲(独立播放源)
*/
private void playPrivateFirstSong() {
if (privateSongList == null || privateSongList.isEmpty()) {
ToastUtil.showShortToast("暂无私人歌曲");
return;
}
MusicBean.DataBean firstSong = privateSongList.get(0);
String url = firstSong.getMusic();
// 情况1:正在播放这首私人歌曲 → 暂停
if (playerManager.isPlaying()
&& playerManager.isPlayingFromPrivate()
&& url.equals(playerManager.getCurrentPlayingMusicUrl())) {
playerManager.pause();
sr_start.setImageResource(R.mipmap.img_lan_bf);
ToastUtil.showShortToast("已暂停");
return;
}
// 情况2:已暂停,但可以恢复(播放器未释放)
if (playerManager.canResumePlaying(url)) {
playerManager.resume();
sr_start.setImageResource(R.mipmap.img_lan_zt);
ToastUtil.showShortToast("继续播放: " + firstSong.getTitle());
return;
}
// 情况3:首次播放 or 已释放 → 重新准备
playerManager.playFromExternalList(requireContext(), privateSongList, 0);
sr_start.setImageResource(R.mipmap.img_lan_zt);
rotationHelper.stopRotation();
ToastUtil.showShortToast("播放私人歌曲: " + firstSong.getTitle());
}
/**
* 播放轻音乐歌单的第一首歌曲(独立播放源)
*/
private void playQingyinFirstSong() {
if (qySongList == null || qySongList.isEmpty()) {
ToastUtil.showShortToast("暂无轻音乐");
return;
}
MusicBean.DataBean firstSong = qySongList.get(0);
String url = firstSong.getMusic();
// 情况1:正在播放这首轻音乐 → 暂停
if (playerManager.isPlaying()
&& playerManager.isPlayingFromPrivate() // 我们复用 isPlayingFromPrivate 标志
&& url.equals(playerManager.getCurrentPlayingMusicUrl())) {
playerManager.pause();
qy_start.setImageResource(R.mipmap.img_lan_bf); // 显示“播放”图标
ToastUtil.showShortToast("已暂停");
return;
}
// 情况2:已暂停,但可以恢复
if (playerManager.canResumePlaying(url)) {
playerManager.resume();
qy_start.setImageResource(R.mipmap.img_lan_zt); // 显示“暂停”图标
ToastUtil.showShortToast("继续播放: " + firstSong.getTitle());
return;
}
// 情况3:首次播放 or 已释放 → 重新准备
playerManager.playFromExternalList(requireContext(), qySongList, 0);
qy_start.setImageResource(R.mipmap.img_lan_zt); // 暂停图标
rotationHelper.stopRotation(); // 停止主列表旋转动画
ToastUtil.showShortToast("播放轻音乐: " + firstSong.getTitle());
}
private void playXiaoZhongFirstSong(){
if (xzSongList == null || xzSongList.isEmpty()) {
ToastUtil.showShortToast("暂无轻音乐");
return;
}
MusicBean.DataBean firstSong = xzSongList.get(0);
String url = firstSong.getMusic();
// 情况1:正在播放这首轻音乐 → 暂停
if (playerManager.isPlaying()
&& playerManager.isPlayingFromPrivate() // 我们复用 isPlayingFromPrivate 标志
&& url.equals(playerManager.getCurrentPlayingMusicUrl())) {
playerManager.pause();
xz_start.setImageResource(R.mipmap.img_lan_bf); // 显示“播放”图标
ToastUtil.showShortToast("已暂停");
return;
}
// 情况2:已暂停,但可以恢复
if (playerManager.canResumePlaying(url)) {
playerManager.resume();
xz_start.setImageResource(R.mipmap.img_lan_zt); // 显示“暂停”图标
ToastUtil.showShortToast("继续播放: " + firstSong.getTitle());
return;
}
// 情况3:首次播放 or 已释放 → 重新准备
playerManager.playFromExternalList(requireContext(), qySongList, 0);
xz_start.setImageResource(R.mipmap.img_lan_zt); // 暂停图标
rotationHelper.stopRotation(); // 停止主列表旋转动画
ToastUtil.showShortToast("播放轻音乐: " + firstSong.getTitle());
}
@Override
public void onDestroy() {
playerManager.release();
rotationHelper.stopRotation();
super.onDestroy();
}
}
package com.weishitech.qichechangtingyinyue.utils;
import android.content.Context;
import android.media.AudioAttributes;
import android.media.MediaPlayer;
import com.weishitech.qichechangtingyinyue.bean.MusicBean;
import java.util.List;
public class MusicPlayerManager {
private MediaPlayer mediaPlayer;
private OnPlaybackStateChangedListener listener;
private int currentPlayingPosition = -1;
private boolean isPlayingFromPrivate = false;
public boolean isPlayingFromPrivate() { return isPlayingFromPrivate; }
public void setPlayingFromPrivate(boolean flag) { this.isPlayingFromPrivate = flag; }
public interface OnPlaybackStateChangedListener {
void onPlaying(int position);
void onPaused();
void onCompletion();
void onError(String errorMsg);
}
public void setOnPlaybackStateChangedListener(OnPlaybackStateChangedListener listener) {
this.listener = listener;
}
// 在 MusicPlayerManager.java 中新增:
public void play(Context context, String musicUrl) {
play(context, -1, musicUrl); // 用 -1 表示“无位置”
}
public void play(Context context, int position, String musicUrl) {
if (position == currentPlayingPosition && mediaPlayer != null && mediaPlayer.isPlaying()) {
return; // 正在播放同一首
}
try {
release();
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(musicUrl);
mediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build());
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(mp -> {
mp.start();
currentPlayingPosition = position;
if (listener != null) listener.onPlaying(position);
});
mediaPlayer.setOnCompletionListener(mp -> {
if (listener != null) listener.onCompletion();
});
mediaPlayer.setOnErrorListener((mp, what, extra) -> {
if (listener != null) listener.onError("播放错误: " + what);
return true;
});
} catch (Exception e) {
e.printStackTrace();
if (listener != null) listener.onError("无法播放音乐");
}
}
public void pause() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
if (listener != null) listener.onPaused();
}
}
public void resume() {
if (mediaPlayer != null && !mediaPlayer.isPlaying()) {
mediaPlayer.start();
if (listener != null) listener.onPlaying(currentPlayingPosition);
}
}
public boolean isPlaying() {
return mediaPlayer != null && mediaPlayer.isPlaying();
}
public void release() {
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
currentPlayingPosition = -1;
}
public int getCurrentPlayingPosition() {
return currentPlayingPosition;
}
// 新增:获取当前播放的 URL
public String getCurrentPlayingMusicUrl() {
return currentPlayingUrl;
}
// 新增字段
private String currentPlayingUrl = null;
// public void setOnCompletionListener(Runnable listener) {
// if (mediaPlayer != null) {
// mediaPlayer.setOnCompletionListener(mp -> {
// if (listener != null) listener.run();
// });
// }
// }
public void playFromExternalList(Context context, List<MusicBean.DataBean> list, int startIndex) {
if (list == null || list.isEmpty() || startIndex < 0 || startIndex >= list.size()) {
return;
}
MusicBean.DataBean bean = list.get(startIndex);
try {
release(); // 先释放旧资源
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(bean.getMusic());
mediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build());
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(mp -> {
mp.start();
currentPlayingPosition = -1; // 表示不在主列表中
currentPlayingUrl = bean.getMusic();
isPlayingFromPrivate = true; // 新增标志位
if (listener != null) listener.onPlaying(-1); // -1 表示来自外部列表
});
mediaPlayer.setOnCompletionListener(mp -> {
if (listener != null) listener.onCompletion();
});
mediaPlayer.setOnErrorListener((mp, what, extra) -> {
if (listener != null) listener.onError("播放错误: " + what);
return true;
});
} catch (Exception e) {
e.printStackTrace();
if (listener != null) listener.onError("无法播放音乐");
}
}
/**
* 判断是否已加载指定 URL 的音乐并处于暂停状态
*/
/**
* 判断是否可以继续播放某首歌(已加载且暂停)
*/
public boolean canResumePlaying(String musicUrl) {
return mediaPlayer != null // 播放器还活着
&& !mediaPlayer.isPlaying() // 当前没播
&& currentPlayingUrl != null
&& currentPlayingUrl.equals(musicUrl);
}
}
这个playXiaoZhongFirstSong方法我播放小众音乐ToastUtil.showShortToast("播放小众音乐: " + firstSong.getTitle());这个提示是对的但是没有播放对的音乐