RecyclerView实现按时间分组手机相册效果

RecyclerView通常只有一个header和footer,但是像手机相册这种布局每个item都会有一个header该怎么办,其中一种办法就是RecyclerView嵌套RecyclerView,虽然能实现但是并不怎么友好,如何只创建一个RecyclerView就实现这种布局呢?
在github上找到了SectionedRecyclerView,不需要改动RecyclerView,定义adapter的时候只需要继承SectionedRecyclerViewAdapter即可,首先来看效果图
在这里插入图片描述
在这里插入图片描述
但是SectionedRecyclerViewAdapter使用的时候比平时的adapter多一些方法,下面简单介绍一下:

  1. SectionedRecyclerView这个库提供了两种adapter,一个是SectionedRecyclerViewAdapter,功能比较完成,有footer,另一个是SimpleSectionedAdapter,顾名思义就是简化版,只是有header,不需要footer
  2. 继承SectionedRecyclerViewAdapter时,通过hasFooterInSection设置是否显示footer布局
    下面贴出继承两种adapter的代码,方法的注释都写在上面了,只是比普通的adapter多了header和footer布局
继承SectionedRecyclerViewAdapter:
/**
 * @Description: 完整的adapter
 * 注意:通过hasFooterInSection()这个方法来设置是否需要显示footer
 * @author: ZhangYW
 * @time: 2019/1/24 9:39
 */
public class MyAdapter extends SectionedRecyclerViewAdapter<MyAdapter.MyHeaderViewHolder, MyAdapter.MyItemViewHolder, MyAdapter.MyFooterViewHolder> {

    private Context mContext;
    private List<MyBean> mList;

    public MyAdapter(Context context, List<MyBean> list) {
        this.mContext = context;
        this.mList = list;
    }

    /**
     * header或者footer的个数
     * @return
     */
    @Override
    protected int getSectionCount() {
        return mList.size();
    }

    /**
     * 每个header或者footer中包含具体的内容个数
     * @return
     */
    @Override
    protected int getItemCountForSection(int section) {
        return mList.get(section).getList().size();
    }

    /**
     * 是否显示footer
     * @param section
     * @return
     */
    @Override
    protected boolean hasFooterInSection(int section) {
        return true;
    }

    /**
     * 渲染具体的HeaderViewHolder
     *
     * @param parent   HeaderViewHolder的容器
     * @param viewType 一个标志,我们根据该标志可以实现渲染不同类型的ViewHolder
     * @return
     */
    @Override
    protected MyHeaderViewHolder onCreateSectionHeaderViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(mContext).inflate(R.layout.item_rv_header, parent, false);
        return new MyHeaderViewHolder(itemView);
    }

    /**
     * 渲染具体的FooterViewHolder
     *
     * @param parent   FooterViewHolder的容器
     * @param viewType 一个标志,我们根据该标志可以实现渲染不同类型的ViewHolder
     * @return
     */
    @Override
    protected MyFooterViewHolder onCreateSectionFooterViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(mContext).inflate(R.layout.item_rv_footer, parent, false);
        return new MyFooterViewHolder(itemView);
    }

    /**
     * 渲染具体的ItemViewHolder
     *
     * @param parent   ItemViewHolder的容器
     * @param viewType 一个标志,我们根据该标志可以实现渲染不同类型的ViewHolder
     * @return
     */
    @Override
    protected MyItemViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(mContext).inflate(R.layout.item_rv_content, parent, false);
        return new MyItemViewHolder(itemView);
    }

    /**
     * 绑定HeaderViewHolder的数据。
     *
     * @param holder
     * @param section 数据源list的下标
     */
    @Override
    protected void onBindSectionHeaderViewHolder(MyHeaderViewHolder holder, int section) {
        MyBean bean = mList.get(section);
        if (null == bean)
            return;
        holder.tv_header_title.setText(bean.getHeader());
    }

    /**
     * 绑定FooterViewHolder的数据。
     *
     * @param holder
     * @param section 数据源list的下标
     */
    @Override
    protected void onBindSectionFooterViewHolder(MyFooterViewHolder holder, int section) {
        MyBean bean = mList.get(section);
        if (null == bean)
            return;
        holder.tv_footer_title.setText(bean.getFooter());
    }

    /**
     * 绑定ItemViewHolder的数据。
     *
     * @param holder
     * @param section 数据源list的下标
     */
    @Override
    protected void onBindItemViewHolder(MyItemViewHolder holder, int section, int position) {
        MyBean bean = mList.get(section);
        if (null == bean)
            return;
        holder.tv_name.setText(bean.getList().get(position).getContent());
        GlideApp.with(mContext)
                .load(R.mipmap.group)
                .placeholder(R.mipmap.ic_launcher)
                .error(R.mipmap.ic_launcher)
                .centerCrop()
                .into(holder.iv_head);
    }

    /**
     * ItemViewHolder
     */
    public class MyItemViewHolder extends RecyclerView.ViewHolder {
        private ImageView iv_head;
        private TextView tv_name;

        public MyItemViewHolder(View itemView) {
            super(itemView);
            iv_head = (ImageView)itemView.findViewById(R.id.item_iv);
            tv_name = (TextView)itemView.findViewById(R.id.item_tv_title);
        }
    }

    /**
     * HeaderViewHolder
     */
    public class MyHeaderViewHolder extends RecyclerView.ViewHolder {
        private TextView tv_header_title;
        public MyHeaderViewHolder(View itemView) {
            super(itemView);
            tv_header_title = (TextView)itemView.findViewById(R.id.item_header_title);
        }
    }

    /**
     * FooterViewHolder
     */
    public class MyFooterViewHolder extends RecyclerView.ViewHolder {
        private TextView tv_footer_title;
        public MyFooterViewHolder(View itemView) {
            super(itemView);
            tv_footer_title = (TextView)itemView.findViewById(R.id.item_footer_title);
        }
    }
继承SimpleSectionedAdapter:
/**
 * @Description: 简单用法 没有footer
 * @author: ZhangYW
 * @time: 2019/1/24 9:38
 */
public class SimpleHeaderAdapter extends SimpleSectionedAdapter<SimpleHeaderAdapter.MyItemViewHolder> {

    private Context mContext;
    private List<MyBean> mList;

    public SimpleHeaderAdapter(Context context, List<MyBean> list) {
        this.mContext = context;
        this.mList = list;

    }


    @Override
    protected String getSectionHeaderTitle(int section) {
        return mList.get(section).getHeader();
    }

    /**
     * header或者footer的个数
     * @return
     */
    @Override
    protected int getSectionCount() {
        return mList.size();
    }

    /**
     * 每个header或者footer中包含具体的内容个数
     * @return
     */
    @Override
    protected int getItemCountForSection(int section) {
        return mList.get(section).getList().size();
    }

    @Override
    protected MyItemViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(mContext).inflate(R.layout.item_rv_content, parent, false);
        return new SimpleHeaderAdapter.MyItemViewHolder(itemView);
    }

    @Override
    protected void onBindItemViewHolder(MyItemViewHolder holder, int section, int position) {
        MyBean bean = mList.get(section);
        if (null == bean)
            return;
        holder.tv_name.setText(bean.getList().get(position).getContent());
        GlideApp.with(mContext)
                .load(R.mipmap.group)
                .placeholder(R.mipmap.ic_launcher)
                .error(R.mipmap.ic_launcher)
                .centerCrop()
                .into(holder.iv_head);
    }

    /**
     * ItemViewHolder
     */
    public class MyItemViewHolder extends RecyclerView.ViewHolder {
        private ImageView iv_head;
        private TextView tv_name;

        public MyItemViewHolder(View itemView) {
            super(itemView);
            iv_head = (ImageView)itemView.findViewById(R.id.item_iv);
            tv_name = (TextView)itemView.findViewById(R.id.item_tv_title);
        }
    }
}

在这里插入图片描述
下载地址:TestSectionedRecyclerView
如果没有积分,请点这里github:TestSectionedRecyclerView

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
RecyclerView可以通过自定义ItemDecoration实现折叠效果。 具体步骤如下: 1. 创建自定义的ItemDecoration类,继承RecyclerView.ItemDecoration。 2. 在该类中重写方法onDraw()和getItemOffsets()。 3. 在onDraw()方法中绘制折叠的效果,可以通过Canvas的clipRect()方法裁剪绘制区域,再通过Canvas的drawRect()方法绘制矩形区域。 4. 在getItemOffsets()方法中设置ItemView的偏移量,使之不被折叠部分遮挡。 5. 在RecyclerView的LayoutManager中设置ItemDecoration,即可实现折叠效果。 下面是一个示例代码: ```java public class FoldItemDecoration extends RecyclerView.ItemDecoration { private int mFoldHeight; // 折叠高度 public FoldItemDecoration(int foldHeight) { mFoldHeight = foldHeight; } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { View child = parent.getChildAt(i); int bottom = child.getBottom(); if (bottom > mFoldHeight) { // 超过折叠高度的部分才进行折叠 c.save(); c.clipRect(parent.getPaddingLeft(), mFoldHeight, parent.getWidth() - parent.getPaddingRight(), bottom); c.drawRect(parent.getPaddingLeft(), mFoldHeight, parent.getWidth() - parent.getPaddingRight(), bottom, new Paint(Color.WHITE)); c.restore(); } } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.bottom = mFoldHeight; } } ``` 在LayoutManager中设置ItemDecoration: ```java int foldHeight = 200; // 折叠高度 FoldItemDecoration decoration = new FoldItemDecoration(foldHeight); recyclerView.addItemDecoration(decoration); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤独的冥王星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值