3.Android高仿网易云音乐-首页复杂发现界面布局和功能/RecyclerView复杂布局

0.效果图

3.Android高仿网易云音乐-首页复杂发现界面布局和功能/RecyclerView复杂布局

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

1.整体分析

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

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

2.轮播图

2.1 布局

<?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> 

2.2 显示数据

//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())); 

按钮

3.1 布局

<?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> 

3.2 显示数据

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); } 

4.推荐歌单

4.1 布局

<?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> 

4.2 显示数据

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()); } 

5. 底部

5.1 布局

<?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> 

5.2 显示数据

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

6.迷你控制条

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

7.播放列表弹窗

/**  * 播放列表对话框  */ 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()));     } }  

感谢你的阅读,更多文章请关注我们,点击,评论,转发支持。

发表评论

相关文章