经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
Android实现网易云音乐高仿版流程
来源:jb51  时间:2022/8/1 13:09:04  对本文有异议

效果图

效果图依次为发现界面顶部,包含首页轮播图,水平滚动的按钮,推荐歌单;然后是发现界面推荐单曲,点击单曲就是直接进入播放界面;最后是全局播放控制条上点击播放列表按钮显示的播放列表弹窗。

整体分析

整体使用RecycerView实现,每个不同的块是一个Item,例如:轮播图是一个Item,按钮也是,推荐歌单和下面的歌单是,推荐单曲,还有最后的自定义首页那块也是一样。

提示:之所以把推荐歌单下面的歌单和推荐歌单标题放一个Item,主要是首页要实现自定义顺序功能,更方便管理。

轮播图

布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. xmlns:app="http://schemas.android.com/apk/res-auto"
  5. android:layout_height="wrap_content"
  6. android:layout_margin="@dimen/padding_outer">
  7. <com.youth.banner.Banner
  8. android:id="@+id/banner"
  9. android:layout_width="0dp"
  10. android:layout_height="0dp"
  11. app:layout_constraintDimensionRatio="H,0.389"
  12. app:layout_constraintLeft_toLeftOf="parent"
  13. app:layout_constraintRight_toRightOf="parent"
  14. app:layout_constraintTop_toTopOf="parent" />
  15. </androidx.constraintlayout.widget.ConstraintLayout>

显示数据

  1. //banner
  2. BannerData data = (BannerData) d;
  3. Banner bannerView = holder.getView(R.id.banner);
  4. BannerImageAdapter<Ad> bannerImageAdapter = new BannerImageAdapter<Ad>(data.getData()) {
  5. @Override
  6. public void onBindView(BannerImageHolder holder, Ad data, int position, int size) {
  7. ImageUtil.show(getContext(), (ImageView) holder.itemView, data.getIcon());
  8. }
  9. };
  10. bannerView.setAdapter(bannerImageAdapter);
  11. bannerView.setOnBannerListener(onBannerListener);
  12. bannerView.setBannerRound(DensityUtil.dip2px(getContext(), 10));
  13. //添加生命周期观察者
  14. bannerView.addBannerLifecycleObserver(fragment);
  15. bannerView.setIndicator(new CircleIndicator(getContext()));

按钮

布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:paddingVertical="@dimen/padding_outer"
  6. android:scrollbars="none">
  7. <LinearLayout
  8. android:id="@+id/container"
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:orientation="horizontal"
  12. android:paddingHorizontal="@dimen/padding_meddle">
  13. </LinearLayout>
  14. </HorizontalScrollView>

显示数据

  1. LinearLayout container = holder.getView(R.id.container);
  2. if (container.getChildCount() > 0) {
  3. //已经添加了
  4. return;
  5. }
  6. //横向显示5个半
  7. float containerWidth = ScreenUtil.getScreenWith(container.getContext()) - DensityUtil.dip2px(container.getContext(), 10 * 2);
  8. int itemWidth = (int) (containerWidth / 5.5);
  9. DiscoveryButtonBinding binding;
  10. LinearLayout.LayoutParams layoutParams;
  11. for (IconTitleButtonData it : data.getData()) {
  12. binding = DiscoveryButtonBinding.inflate(LayoutInflater.from(getContext()));
  13. binding.icon.setImageResource(it.getIcon());
  14. binding.title.setText(it.getTitle());
  15. if (it.getIcon() == R.drawable.day_recommend) {
  16. SuperViewUtil.show(binding.more);
  17. //显示日期
  18. binding.more.setText(String.valueOf(SuperDateUtil.currentDay()));
  19. }
  20. //设置点击事件
  21. binding.getRoot().setOnClickListener(new View.OnClickListener() {
  22. @Override
  23. public void onClick(View v) {
  24. }
  25. });
  26. layoutParams = new LinearLayout.LayoutParams(itemWidth, ViewGroup.LayoutParams.WRAP_CONTENT);
  27. container.addView(binding.getRoot(), layoutParams);
  28. }

推荐歌单

布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:orientation="vertical">
  6. <include layout="@layout/item_discovery_title" />
  7. <androidx.recyclerview.widget.RecyclerView
  8. android:id="@+id/list"
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:paddingHorizontal="@dimen/padding_outer"
  12. android:paddingBottom="@dimen/d5" />
  13. </LinearLayout>

显示数据

  1. private void bindSheetData(BaseViewHolder holder, SheetData data) {
  2. //设置标题,将标题放到每个具体的item上,好处是方便整体排序
  3. holder.setText(R.id.title, R.string.recommend_sheet);
  4. //显示更多容器
  5. holder.setVisible(R.id.more, true);
  6. holder.getView(R.id.more).setOnClickListener(v -> {
  7. });
  8. RecyclerView listView = holder.getView(R.id.list);
  9. if (listView.getAdapter() == null) {
  10. //设置显示3列
  11. GridLayoutManager layoutManager = new GridLayoutManager(listView.getContext(), 3);
  12. listView.setLayoutManager(layoutManager);
  13. sheetAdapter = new SheetAdapter(R.layout.item_sheet);
  14. //item点击
  15. sheetAdapter.setOnItemClickListener(new OnItemClickListener() {
  16. @Override
  17. public void onItemClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
  18. if (discoveryAdapterListener != null) {
  19. discoveryAdapterListener.onSheetClick((Sheet) adapter.getItem(position));
  20. }
  21. }
  22. });
  23. listView.setAdapter(sheetAdapter);
  24. GridDividerItemDecoration itemDecoration = new GridDividerItemDecoration(getContext(), (int) DensityUtil.dip2px(getContext(), 5F));
  25. listView.addItemDecoration(itemDecoration);
  26. }
  27. sheetAdapter.setNewInstance(data.getData());
  28. }

底部

布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content"
  6. android:layout_marginVertical="@dimen/padding_outer"
  7. android:gravity="center_horizontal"
  8. android:orientation="vertical">
  9. <androidx.appcompat.widget.LinearLayoutCompat
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:gravity="center_vertical">
  13. <TextView
  14. android:id="@+id/refresh_button"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:drawableLeft="@drawable/refresh"
  18. android:gravity="center_vertical"
  19. android:text="@string/click_refresh"
  20. android:textColor="@color/link"
  21. android:textSize="@dimen/text_small" />
  22. <TextView
  23. android:layout_width="wrap_content"
  24. android:layout_height="wrap_content"
  25. android:layout_marginLeft="@dimen/padding_small"
  26. android:text="@string/change_content"
  27. android:textColor="@color/black80"
  28. android:textSize="@dimen/text_small" />
  29. </androidx.appcompat.widget.LinearLayoutCompat>
  30. <com.google.android.material.button.MaterialButton
  31. android:id="@+id/custom"
  32. style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
  33. android:layout_width="wrap_content"
  34. android:layout_height="@dimen/d30"
  35. android:layout_marginTop="@dimen/padding_outer"
  36. android:backgroundTint="?attr/colorSurface"
  37. android:insetTop="0dp"
  38. android:insetBottom="0dp"
  39. android:text="@string/custom_discovery"
  40. android:textColor="@color/black80"
  41. android:textSize="@dimen/text_small"
  42. app:cornerRadius="@dimen/d15"
  43. app:elevation="0dp"
  44. app:strokeColor="@color/black80"
  45. app:strokeWidth="@dimen/d0_5" />
  46. </LinearLayout>

显示数据

  1. holder.getView(R.id.refresh_button).setOnClickListener(v -> discoveryAdapterListener.onRefreshClick());
  2. holder.getView(R.id.custom).setOnClickListener(v -> discoveryAdapterListener.onCustomDiscoveryClick());

迷你控制条

他是一个自定义Fragment,哪里要显示就放到哪里就行了。

播放列表弹窗

  1. /**
  2. * 播放列表对话框
  3. */
  4. public class MusicPlayListDialogFragment extends BaseViewModelBottomSheetDialogFragment<FragmentDialogAudioPlayListBinding> {
  5. ...
  6. @Override
  7. protected void initListeners() {
  8. super.initListeners();
  9. //删除所有按钮点击
  10. binding.deleteAll.setOnClickListener(new View.OnClickListener() {
  11. @Override
  12. public void onClick(View v) {
  13. //关闭对话框
  14. dismiss();
  15. //删除全部音乐
  16. getMusicListManager().deleteAll();
  17. }
  18. });
  19. //item中子控件点击
  20. //删除按钮点击
  21. adapter.addChildClickViewIds(R.id.delete);
  22. adapter.setOnItemChildClickListener(new OnItemChildClickListener() {
  23. @Override
  24. public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
  25. //由于这里只有一个按钮点击
  26. //所以可以不判断
  27. if (R.id.delete == view.getId()) {
  28. //删除按钮点击
  29. removeItem(position);
  30. }
  31. }
  32. });
  33. //循环模式点击
  34. binding.loopModel.setOnClickListener(new View.OnClickListener() {
  35. @Override
  36. public void onClick(View v) {
  37. //更改循环模式
  38. getMusicListManager().changeLoopModel();
  39. //显示循环模式
  40. showLoopModel();
  41. }
  42. });
  43. //设置item点击事件
  44. adapter.setOnItemClickListener(new OnItemClickListener() {
  45. @Override
  46. public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
  47. //关闭dialog
  48. //可以根据具体的业务逻辑来决定是否关闭
  49. dismiss();
  50. //播放点击的这首音乐
  51. getMusicListManager().play(getMusicListManager().getDatum().get(position));
  52. }
  53. });
  54. }
  55. private void removeItem(int position) {
  56. adapter.removeAt(position);
  57. //从列表管理器中删除
  58. getMusicListManager().delete(position);
  59. showCount();
  60. }
  61. /**
  62. * 显示循环模式
  63. */
  64. private void showLoopModel() {
  65. PlayListUtil.showLoopModel(getMusicListManager().getLoopModel(), binding.loopModel);
  66. }
  67. private void showCount() {
  68. binding.count.setText(String.format("(%d)", getMusicListManager().getDatum().size()));
  69. }
  70. }

到此这篇关于Android实现网易云音乐高仿版流程的文章就介绍到这了,更多相关Android网易云音乐内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号