package com.weishitech.qichechangtingyinyue.fragment.home;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CircleCrop;
import com.hfd.common.base.BaseActivity;
import com.hfd.common.util.ToastUtil;
import com.weishitech.qichechangtingyinyue.R;
import com.weishitech.qichechangtingyinyue.utils.MusicPlayerManager;
import com.weishitech.qichechangtingyinyue.utils.OnMultiClickListener;
public class LyricsActivity extends BaseActivity {
// UI Views
TextView tv_back, tv_song_name, tv_sing_name, tv_start_time, tv_end_time;
ImageView iv_sing_logo, iv_tj, iv_gd, iv_xh, iv_sys, iv_bf, iv_xys, iv_zjbf;
SeekBar seekbar;
// 播放管理器
private MusicPlayerManager playerManager;
private boolean isBoundToCurrentSong = false; // 是否已绑定当前歌曲
// 数据接收字段
private String title, singer, coverUrl, musicUrl;
private int songPosition;
// 进度更新
private final Handler handler = new Handler();
private final Runnable updateProgressRunnable = new Runnable() {
@Override
public void run() {
if (playerManager != null && playerManager.isPlaying()) {
int currentPosition = playerManager.getCurrentPosition();
int duration = playerManager.getDuration();
if (duration > 0) {
seekbar.setMax(duration);
seekbar.setProgress(currentPosition);
// 更新时间文本(格式 mm:ss)
tv_start_time.setText(formatTime(currentPosition));
tv_end_time.setText(formatTime(duration));
}
}
handler.postDelayed(this, 1000); // 每秒更新一次
}
};
@Override
protected int setLayout() {
return R.layout.activity_lyrics;
}
@Override
protected void setView() {
tv_back = fvbi(R.id.tv_back);
iv_sing_logo = fvbi(R.id.iv_sing_logo);
tv_song_name = fvbi(R.id.tv_song_name);
tv_sing_name = fvbi(R.id.tv_sing_name);
iv_tj = fvbi(R.id.iv_tj);
iv_gd = fvbi(R.id.iv_gd);
seekbar = fvbi(R.id.seekbar);
tv_start_time = fvbi(R.id.tv_start_time);
tv_end_time = fvbi(R.id.tv_end_time);
iv_xh = fvbi(R.id.iv_xh);
iv_sys = fvbi(R.id.iv_sys);
iv_bf = fvbi(R.id.iv_bf);
iv_xys = fvbi(R.id.iv_xys);
iv_zjbf = fvbi(R.id.iv_zjbf);
}
@Override
protected void setData() {
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
title = bundle.getString("title");
singer = bundle.getString("singer");
coverUrl = bundle.getString("cover_url");
musicUrl = bundle.getString("music_url");
songPosition = bundle.getInt("position", -1);
tv_song_name.setText(title);
tv_sing_name.setText(singer);
Glide.with(this)
.load(coverUrl)
.transform(new CircleCrop())
.into(iv_sing_logo);
}
// 初始化播放器
//使用单例
playerManager = MusicPlayerManager.getInstance();
// 注册播放状态监听
setupPlaybackListener();
// 绑定当前歌曲(检查是否已在播放)
bindToCurrentSong();
}
@Override
protected void setClick() {
tv_back.setOnClickListener(v -> finish());
// 播放/暂停按钮
iv_bf.setOnClickListener(v -> {
if (!isBoundToCurrentSong) {
ToastUtil.showShortToast("暂无歌曲信息");
return;
}
if (playerManager.isPlaying()) {
playerManager.pause();
} else {
playerManager.resume();
}
updatePlayButtonIcon();
});
// SeekBar 拖动控制
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
tv_start_time.setText(formatTime(progress));
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// 用户开始拖动
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// 用户停止拖动,跳转到指定位置
if (playerManager != null && isBoundToCurrentSong) {
playerManager.seekTo(seekbar.getProgress());
}
}
});
}
private void bindToCurrentSong() {
if (musicUrl == null || title == null) return;
boolean isPlaying = playerManager.isPlaying();
int currentPos = playerManager.getCurrentPlayingPosition();
// 判断是否就是当前正在播放的歌曲
if (isPlaying && currentPos == songPosition) {
// 是同一首歌 → 直接同步状态
isBoundToCurrentSong = true;
updatePlayButtonIcon(); // 显示“暂停”
startUpdatingProgress(); // 开始更新进度条
} else {
// 不是当前播放的 → 准备播放这首
playerManager.play(this, songPosition, musicUrl);
isBoundToCurrentSong = true;
updatePlayButtonIcon(); // 默认播放中
startUpdatingProgress();
}
}
private void setupPlaybackListener() {
playerManager.setOnPlaybackStateChangedListener(new MusicPlayerManager.OnPlaybackStateChangedListener() {
@Override
public void onPlaying(int position) {
if (position == songPosition) {
runOnUiThread(() -> {
updatePlayButtonIcon();
startUpdatingProgress();
});
}
}
@Override
public void onPaused() {
runOnUiThread(() -> {
updatePlayButtonIcon();
stopUpdatingProgress();
});
}
@Override
public void onCompletion() {
runOnUiThread(() -> {
updatePlayButtonIcon();
stopUpdatingProgress();
seekbar.setProgress(0);
tv_start_time.setText("00:00");
});
}
@Override
public void onError(String errorMsg) {
runOnUiThread(() -> {
ToastUtil.showShortToast("播放出错:" + errorMsg);
updatePlayButtonIcon();
stopUpdatingProgress();
});
}
});
}
private void updatePlayButtonIcon() {
if (playerManager.isPlaying()) {
iv_bf.setImageResource(R.mipmap.img_lan_zt); // 暂停图标
} else {
iv_bf.setImageResource(R.mipmap.img_lan_bf); // 播放图标
}
}
private void startUpdatingProgress() {
stopUpdatingProgress(); // 防止重复
handler.postDelayed(updateProgressRunnable, 0);
}
private void stopUpdatingProgress() {
handler.removeCallbacks(updateProgressRunnable);
}
@Override
public void onResume() {
super.onResume();
// 页面可见时尝试恢复状态
if (isBoundToCurrentSong) {
updatePlayButtonIcon();
}
}
@Override
protected void onPause() {
super.onPause();
// 可选:不移除监听,让后台也能播放
}
@Override
protected void onDestroy() {
stopUpdatingProgress();
// 注意:不要 release() playerManager,否则其他页面会中断
// playerManager.release(); ❌ 不要在这里释放
super.onDestroy();
}
// 时间格式化工具
private String formatTime(int milliseconds) {
int seconds = milliseconds / 1000;
int minutes = seconds / 60;
seconds = seconds % 60;
return String.format("%02d:%02d", minutes, seconds);
}
}
package com.weishitech.qichechangtingyinyue.fragment.home;
import android.annotation.SuppressLint;
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; // 是否由主流程控制播放状态
private int lastPlayedPosition = -1;
// 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 = MusicPlayerManager.getInstance(); //单例获取
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() {
// 来自主列表 → 播放下一首主歌
if (!playerManager.isPlayingFromPrivate()) {
playNextSong();
return;
}
// 来自外部歌单 → 尝试播放下一首
boolean hasNext = playerManager.playNextInExternalList();
if (!hasNext) {
ToastUtil.showShortToast("当前歌单已播放完毕");
updateStartButtonIcons(); // 所有按钮恢复“播放”图标
}
}
@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);
//点击top条目跳转到歌词页面
songTopAdapter.setOnItemClickListener((position, dataBean) -> {
// 创建 Bundle 传递数据
Bundle bundle = new Bundle();
bundle.putString("title", dataBean.getTitle());
bundle.putString("singer", dataBean.getSinger());
bundle.putString("cover_url", dataBean.getCover());
bundle.putString("music_url", dataBean.getMusic());
bundle.putString("time", dataBean.getSongTime());
bundle.putInt("position", position);
// 跳转到 LyricsActivity
toClass(LyricsActivity.class, bundle);
});
//私人音乐适配器
// 从第三个元素(索引=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;
}
@SuppressLint("SetTextI18n")
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());
//使用 post() 延迟更新 adapter,避免在 layout 过程中修改
rv.post(() -> {
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 updateStartButtonIcons() {
sr_start.setImageResource(R.mipmap.img_lan_bf);
qy_start.setImageResource(R.mipmap.img_lan_bf);
xz_start.setImageResource(R.mipmap.img_lan_bf);
}
/**
* 播放私人专属歌单
*/
private void playPrivateFirstSong() {
if (privateSongList == null || privateSongList.isEmpty()) {
ToastUtil.showShortToast("暂无私人歌曲");
return;
}
boolean isPlaying = playerManager.isPlaying();
boolean isFromThisList = "private".equals(playerManager.getCurrentPlaylistTag());
// 如果正在播放该列表中的任意一首 → 暂停
if (isPlaying && isFromThisList) {
playerManager.pause();
sr_start.setImageResource(R.mipmap.img_lan_bf);
ToastUtil.showShortToast("已暂停");
return;
}
// 如果已暂停,且属于该列表 → 恢复(不重新 prepare)
if (!isPlaying && isFromThisList) {
playerManager.resume();
sr_start.setImageResource(R.mipmap.img_lan_zt);
int currentIndex = playerManager.getCurrentExternalIndex();
MusicBean.DataBean currentSong = privateSongList.get(currentIndex);
ToastUtil.showShortToast("继续播放: " + currentSong.getTitle());
return;
}
// 否则:首次播放 or 切换到新列表 → 从 index=0 开始
playerManager.playFromExternalList(requireContext(), privateSongList, 0, "private");
playerManager.setPlayingFromPrivate(true);
sr_start.setImageResource(R.mipmap.img_lan_zt);
rotationHelper.stopRotation();
MusicBean.DataBean firstSong = privateSongList.get(0);
ToastUtil.showShortToast("播放私人歌曲: " + firstSong.getTitle());
}
private void playQingyinFirstSong() {
if (qySongList == null || qySongList.isEmpty()) {
ToastUtil.showShortToast("暂无私人歌曲");
return;
}
boolean isPlaying = playerManager.isPlaying();
boolean isFromThisList = "private".equals(playerManager.getCurrentPlaylistTag());
// 如果正在播放该列表中的任意一首 → 暂停
if (isPlaying && isFromThisList) {
playerManager.pause();
qy_start.setImageResource(R.mipmap.img_lan_bf);
ToastUtil.showShortToast("已暂停");
return;
}
// 如果已暂停,且属于该列表 → 恢复(不重新 prepare)
if (!isPlaying && isFromThisList) {
playerManager.resume();
qy_start.setImageResource(R.mipmap.img_lan_zt);
return;
}
// 否则:首次播放 or 切换到新列表 → 从 index=0 开始
playerManager.playFromExternalList(requireContext(), qySongList, 0, "private");
playerManager.setPlayingFromPrivate(true);
qy_start.setImageResource(R.mipmap.img_lan_zt);
rotationHelper.stopRotation();
MusicBean.DataBean firstSong = qySongList.get(0);
ToastUtil.showShortToast("播放轻音歌曲: " + firstSong.getTitle());
}
private void playXiaoZhongFirstSong() {
if (xzSongList == null || xzSongList.isEmpty()) {
ToastUtil.showShortToast("暂无私人歌曲");
return;
}
boolean isPlaying = playerManager.isPlaying();
boolean isFromThisList = "private".equals(playerManager.getCurrentPlaylistTag());
// 如果正在播放该列表中的任意一首 → 暂停
if (isPlaying && isFromThisList) {
playerManager.pause();
xz_start.setImageResource(R.mipmap.img_lan_bf);
ToastUtil.showShortToast("已暂停");
return;
}
// 如果已暂停,且属于该列表 → 恢复(不重新 prepare)
if (!isPlaying && isFromThisList) {
playerManager.resume();
xz_start.setImageResource(R.mipmap.img_lan_zt);
int currentIndex = playerManager.getCurrentExternalIndex();
MusicBean.DataBean currentSong = xzSongList.get(currentIndex);
ToastUtil.showShortToast("继续播放: " + currentSong.getTitle());
return;
}
// 否则:首次播放 or 切换到新列表 → 从 index=0 开始
playerManager.playFromExternalList(requireContext(), xzSongList, 0, "private");
playerManager.setPlayingFromPrivate(true);
xz_start.setImageResource(R.mipmap.img_lan_zt);
rotationHelper.stopRotation();
MusicBean.DataBean firstSong = xzSongList.get(0);
ToastUtil.showShortToast("播放小众歌曲: " + firstSong.getTitle());
}
@Override
public void onDestroy() {
// playerManager.release();
rotationHelper.stopRotation();
super.onDestroy();
}
}
这是这两个的完整页面代码你看看怎么修改
最新发布