Android实现网易云音乐 * 版流程

作者:爱上学习啊 时间:2023-05-13 22:08:50 

效果图

Android实现网易云音乐 * 版流程

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

整体分析

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

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

轮播图

布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_height="wrap_content"
   android:layout_margin="@dimen/padding_outer">
   <com.youth.banner.Banner
       android:id="@+id/banner"
       android:layout_width="0dp"
       android:layout_height="0dp"
       app:layout_constraintDimensionRatio="H,0.389"
       app:layout_constraintLeft_toLeftOf="parent"
       app:layout_constraintRight_toRightOf="parent"
       app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

显示数据

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

按钮

布局

<?xml version="1.0" encoding="utf-8"?>
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:paddingVertical="@dimen/padding_outer"
   android:scrollbars="none">
   <LinearLayout
       android:id="@+id/container"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="horizontal"
       android:paddingHorizontal="@dimen/padding_meddle">
   </LinearLayout>
</HorizontalScrollView>

显示数据

LinearLayout container = holder.getView(R.id.container);
if (container.getChildCount() > 0) {
   //已经添加了
   return;
}
//横向显示5个半
float containerWidth = ScreenUtil.getScreenWith(container.getContext()) - DensityUtil.dip2px(container.getContext(), 10 * 2);
int itemWidth = (int) (containerWidth / 5.5);
DiscoveryButtonBinding binding;
LinearLayout.LayoutParams layoutParams;
for (IconTitleButtonData it : data.getData()) {
   binding = DiscoveryButtonBinding.inflate(LayoutInflater.from(getContext()));
   binding.icon.setImageResource(it.getIcon());
   binding.title.setText(it.getTitle());
   if (it.getIcon() == R.drawable.day_recommend) {
       SuperViewUtil.show(binding.more);
       //显示日期
       binding.more.setText(String.valueOf(SuperDateUtil.currentDay()));
   }
   //设置点击事件
   binding.getRoot().setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
       }
   });
   layoutParams = new LinearLayout.LayoutParams(itemWidth, ViewGroup.LayoutParams.WRAP_CONTENT);
   container.addView(binding.getRoot(), layoutParams);
}

推荐歌单

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:orientation="vertical">
   <include layout="@layout/item_discovery_title" />
   <androidx.recyclerview.widget.RecyclerView
       android:id="@+id/list"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:paddingHorizontal="@dimen/padding_outer"
       android:paddingBottom="@dimen/d5" />
</LinearLayout>

显示数据

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

底部

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_marginVertical="@dimen/padding_outer"
   android:gravity="center_horizontal"
   android:orientation="vertical">
   <androidx.appcompat.widget.LinearLayoutCompat
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:gravity="center_vertical">
       <TextView
           android:id="@+id/refresh_button"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:drawableLeft="@drawable/refresh"
           android:gravity="center_vertical"
           android:text="@string/click_refresh"
           android:textColor="@color/link"
           android:textSize="@dimen/text_small" />
       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_marginLeft="@dimen/padding_small"
           android:text="@string/change_content"
           android:textColor="@color/black80"
           android:textSize="@dimen/text_small" />
   </androidx.appcompat.widget.LinearLayoutCompat>
   <com.google.android.material.button.MaterialButton
       android:id="@+id/custom"
       style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
       android:layout_width="wrap_content"
       android:layout_height="@dimen/d30"
       android:layout_marginTop="@dimen/padding_outer"
       android:backgroundTint="?attr/colorSurface"
       android:insetTop="0dp"
       android:insetBottom="0dp"
       android:text="@string/custom_discovery"
       android:textColor="@color/black80"
       android:textSize="@dimen/text_small"
       app:cornerRadius="@dimen/d15"
       app:elevation="0dp"
       app:strokeColor="@color/black80"
       app:strokeWidth="@dimen/d0_5" />
</LinearLayout>

显示数据

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

迷你控制条

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

播放列表弹窗

/**
* 播放列表对话框
*/
public class MusicPlayListDialogFragment extends BaseViewModelBottomSheetDialogFragment<FragmentDialogAudioPlayListBinding> {
   ...
   @Override
   protected void initListeners() {
       super.initListeners();
       //删除所有按钮点击
       binding.deleteAll.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               //关闭对话框
               dismiss();
               //删除全部音乐
               getMusicListManager().deleteAll();
           }
       });
       //item中子控件点击
       //删除按钮点击
       adapter.addChildClickViewIds(R.id.delete);
       adapter.setOnItemChildClickListener(new OnItemChildClickListener() {
           @Override
           public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
               //由于这里只有一个按钮点击
               //所以可以不判断
               if (R.id.delete == view.getId()) {
                   //删除按钮点击
                   removeItem(position);
               }
           }
       });
       //循环模式点击
       binding.loopModel.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               //更改循环模式
               getMusicListManager().changeLoopModel();
               //显示循环模式
               showLoopModel();
           }
       });
       //设置item点击事件
       adapter.setOnItemClickListener(new OnItemClickListener() {
           @Override
           public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
               //关闭dialog
               //可以根据具体的业务逻辑来决定是否关闭
               dismiss();
               //播放点击的这首音乐
               getMusicListManager().play(getMusicListManager().getDatum().get(position));
           }
       });
   }
   private void removeItem(int position) {
       adapter.removeAt(position);
       //从列表管理器中删除
       getMusicListManager().delete(position);
       showCount();
   }
   /**
    * 显示循环模式
    */
   private void showLoopModel() {
       PlayListUtil.showLoopModel(getMusicListManager().getLoopModel(), binding.loopModel);
   }
   private void showCount() {
       binding.count.setText(String.format("(%d)", getMusicListManager().getDatum().size()));
   }
}

来源:https://blog.csdn.net/woblog/article/details/125956217

标签:Android,网易云,音乐, ,
0
投稿

猜你喜欢

  • SpringBoot整合MyCat实现读写分离的方法

    2022-03-05 23:37:45
  • Android判断Activity是否在最上层的方法

    2023-05-09 05:31:01
  • android自定义按钮示例(重写imagebutton控件实现图片按钮)

    2021-06-13 07:55:19
  • C语言中魔性的float浮点数精度问题

    2022-08-12 08:59:26
  • Java中Range函数的简单介绍

    2023-10-18 05:33:35
  • C#微信公众号开发之服务器配置

    2023-03-12 15:02:50
  • Android实现随手指移动小球

    2021-06-03 23:38:46
  • Java编程常见内存溢出异常与代码示例

    2021-12-14 14:45:08
  • Java实现简单无界面五子棋

    2022-07-10 12:06:02
  • 解决微服务中关于用户token处理到的坑

    2022-05-21 08:31:03
  • WinForm实现自定义右下角提示效果的方法

    2023-01-19 08:19:57
  • springboot+jwt+微信小程序授权登录获取token的方法实例

    2022-07-11 17:53:57
  • Idea中maven项目实现登录验证码功能

    2023-11-29 16:50:51
  • C++ 中的异常抛出和捕获方式

    2021-06-08 21:24:19
  • mybatis 集合嵌套查询和集合嵌套结果的区别说明

    2022-10-12 15:17:02
  • 完美解决SpringCloud-OpenFeign使用okhttp替换不生效问题

    2023-07-03 11:27:25
  • Java基本语法之内部类示例详解

    2023-02-06 14:05:32
  • Android编程实现二级下拉菜单及快速搜索的方法

    2021-06-17 23:23:07
  • .NET C#利用ZXing生成、识别二维码/条形码

    2022-03-25 12:20:45
  • java 中的instanceof用法详解及instanceof是什么意思(推荐)

    2023-06-07 13:52:27
  • asp之家 软件编程 m.aspxhome.com