6

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

 2 years ago
source link: https://www.cnblogs.com/woblog/p/16513959.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

0.效果图

488000-20220724095633943-653093257.png

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

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK