BaseRecyclerViewAdapterHelper源码解读(五) header和footer完善
来源:互联网 发布:程序员三大浪漫 编辑:程序博客网 时间:2024/06/01 10:09
关于header和footer的完善
之前的源码阅读,添加header和footer,但是那个还不够完美,只能是在LinearLayoutManager时使用,在GridLayoutManager中使用会像普通item那样只占一个格子.
此篇文章为BaseRecyclerViewAdapterHelper源码解读第五篇,开源库地址,如果没有看过之前4篇文章的同学可以先去看看,大神可直接跳过.
BaseRecyclerViewAdapterHelper源码解读(一) 封装简单的adapter和万能的BaseViewHolder
BaseRecyclerViewAdapterHelper源码解读(二) 添加header和footer
BaseRecyclerViewAdapterHelper源码解读(三) 添加动画
BaseRecyclerViewAdapterHelper源码解读(四) 上拉加载更多
今天给大家带来BaseRecyclerViewAdapterHelper是关于header和footer完善的主要解决了StaggeredGridLayoutManager和GridLayoutManager在添加header和footer时不跨格子的问题.由于本人才学尚浅,如有有不对的地方,欢迎指正,谢谢.
设置header和footer宽度为跨区域
/** * Called when a view created by this adapter has been attached to a window. * simple to solve item will layout using all * * @param holder */ @Override public void onViewAttachedToWindow(K holder) { super.onViewAttachedToWindow(holder); int type = holder.getItemViewType(); if (type == EMPTY_VIEW || type == HEADER_VIEW || type == FOOTER_VIEW || type == LOADING_VIEW) { //设置为跨区域 比如是StaggeredGridLayoutManager时,header或者footer等应该如何展示 setFullSpan(holder); } else { //添加动画到holder的itemView上,并执行动画 addAnimation(holder); } } /** * When set to true, the item will layout using all span area. That means, if orientation * is vertical, the view will have full width; if orientation is horizontal, the view will * have full height. * if the hold view use StaggeredGridLayoutManager they should using all span area * * @param holder True if this item should traverse all spans. */ protected void setFullSpan(RecyclerView.ViewHolder holder) { if (holder.itemView.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams) { StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager .LayoutParams) holder .itemView.getLayoutParams(); params.setFullSpan(true); } }
当一个view被创建并添加到window时会调用onViewAttachedToWindow()方法,而在此时,我们做一下判断,
如果是空布局,header,footer,加载中布局,那么将该item设置为跨区域.
这样就不会出现在StaggeredGridLayoutManager中上面的那些布局是只占了一个跨度.说不清楚,看图
如果不这样做,那么可能图中的那里标注出来的可能就会是header的效果,而不是跨2格.
设置每个item所占跨度
/** * if asFlow is true, footer/header will arrange like normal item view. * only works when use {@link GridLayoutManager},and it will ignore span size. * 如果asFlow是true的话,那么footer和header就像正常item一样,不会跨区域 * 默认是false,header和footer都占满屏幕 */ private boolean headerViewAsFlow, footerViewAsFlow; /** * 设置header不跨区域 就像正常item * true:不跨区域 false:跨区域 */ public void setHeaderViewAsFlow(boolean headerViewAsFlow) { this.headerViewAsFlow = headerViewAsFlow; } public boolean isHeaderViewAsFlow() { return headerViewAsFlow; } /** * 设置footer不跨区域 就像正常item * true:不跨区域 false:跨区域 */ public void setFooterViewAsFlow(boolean footerViewAsFlow) { this.footerViewAsFlow = footerViewAsFlow; } public boolean isFooterViewAsFlow() { return footerViewAsFlow; } /** * 判断当前type是否是特殊的type */ protected boolean isFixedViewType(int type) { return type == EMPTY_VIEW || type == HEADER_VIEW || type == FOOTER_VIEW || type == LOADING_VIEW; } /** * RecyclerView在开始观察该适配器时调用。 * 请记住,多个RecyclerView可能会观察到相同的适配器。 * <p> * Adapter与RecyclerView关联起来 * 这里面主要是做表格布局管理器的头布局和脚布局自占一行的适配 * * @param recyclerView */ @Override public void onAttachedToRecyclerView(final RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); if (manager instanceof GridLayoutManager) { final GridLayoutManager gridManager = ((GridLayoutManager) manager); //设置adapter中每个Item所占用的跨度数 gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { int type = getItemViewType(position); //如果当前type为header并且asFlow为true:那么header设置为不跨区域,就和正常item一样.只占1格 if (type == HEADER_VIEW && isHeaderViewAsFlow()) { return 1; } if (type == FOOTER_VIEW && isFooterViewAsFlow()) { return 1; } //如果用户没有自定义SpanSizeLookup SpanSizeLookup是用来查询每个item占用的跨度数的实例 if (mSpanSizeLookup == null) { /* 1.如果是特殊的type,那么item的跨度设置为当前gridManager的SpanCount 即如果我设置的是mRecyclerView.setLayoutManager(new GridLayoutManager(this,2)); 那么当前item占2格的跨度 2.如果item不是特殊的item,那么就是占1个格子,不跨 */ return isFixedViewType(type) ? gridManager.getSpanCount() : 1; } else { /* 1.如果是特殊的type,那么item的跨度设置为当前gridManager的SpanCount 即如果我设置的是mRecyclerView.setLayoutManager(new GridLayoutManager(this,2)); 那么当前item占2格的跨度 2.如果item不是特殊的item,那么交给外部调用者来处理每个item应该占多少个格 */ return isFixedViewType(type) ? gridManager.getSpanCount() : mSpanSizeLookup.getSpanSize(gridManager, position - getHeaderLayoutCount()); } } }); } } private SpanSizeLookup mSpanSizeLookup; /** 用于外部调用者设置每个item的跨度,除了header,footer,emptyView,loadMoreView */ public interface SpanSizeLookup { int getSpanSize(GridLayoutManager gridLayoutManager, int position); } /** * @param spanSizeLookup instance to be used to query number of spans occupied by each item 用于查询每个item占用的跨度数的实例 */ public void setSpanSizeLookup(SpanSizeLookup spanSizeLookup) { this.mSpanSizeLookup = spanSizeLookup; }
首先,我们将empty_view
,header_view
,footer_view
,loading_view
这些特殊的布局,单独写个方法去判断是否属于特殊的布局.
并且我们设置了2个属性,用于开发者可能会将布局设置为header(footer)和普通item一样都只占1个格子,而不是占满屏幕(占gridManager的SpanCount个格子).
在RecyclerView在开始观察该适配器时调用onAttachedToRecyclerView()方法,然后在里面判断是否是GridLayoutManager,如果是则
设置adapter中每个Item所占用的跨度数.
getSpanSize()逻辑:
- 如果当前type为header或footer并且asFlow为true:那么header或footer设置为不跨区域,就和正常item一样.只占1格.
- 如果用户没有自定义SpanSizeLookup SpanSizeLookup是用来查询每个item占用的跨度数的实例
- 1.如果是特殊的type,那么item的跨度设置为当前gridManager的SpanCount
即如果我设置的是mRecyclerView.setLayoutManager(new GridLayoutManager(this,2));
那么当前item占2格的跨度
2.如果item不是特殊的item,那么就是占1个格子,不跨
- 1.如果是特殊的type,那么item的跨度设置为当前gridManager的SpanCount
即如果我设置的是mRecyclerView.setLayoutManager(new GridLayoutManager(this,2));
那么当前item占2格的跨度
2.如果item不是特殊的item,那么交给外部调用者来处理每个item应该占多少个格
总结
- 如果是StaggeredGridLayoutManager,那么在onViewAttachedToWindow()时设置它(header,footer)的跨度为整个SpanCount
- 如果是GridLayoutManager,那么在onAttachedToRecyclerView()时设置它(header,footer)的跨度为整个SpanCount
其实就是判断一个item是否是header或者footer,如果是则设置它的跨度为SpanCount.eg:如果是GridLayoutManager,纵向,那么header就占满整个屏幕;
当然也支持把header和footer设置为普通item跨度的.
- BaseRecyclerViewAdapterHelper源码解读(五) header和footer完善
- BaseRecyclerViewAdapterHelper源码解读(二) 添加header和footer
- 20header和footer
- 实现带header和footer功能的RecyclerView——完善篇
- BaseRecyclerViewAdapterHelper源码解读(三) 添加动画
- BaseRecyclerViewAdapterHelper源码解读(六) 分组布局
- BaseRecyclerViewAdapterHelper源码解读(七) 多布局
- BaseRecyclerViewAdapterHelper源码解读(八) 空布局
- BaseRecyclerViewAdapterHelper源码解读(一) 封装简单的adapter和万能的BaseViewHolder
- ReccylerView添加header和footer
- RecyclerView添加Header和Footer
- RecycleView添加header和footer
- RecyclerView添加Header和Footer
- RecyclerView添加Header和Footer
- RecyclerView添加header和footer
- RecyclerView添加header和footer
- RecyclerView 添加 Header 和 Footer
- RecyclerView添加Header和Footer
- 微信Android SDK反编译还原源码 进行修改重新编译
- DWR入门学习案例
- 最长公共前缀(Longest Common Prefix)
- Camera2开发之CameraDevice类
- Oracle基本用法补充学习
- BaseRecyclerViewAdapterHelper源码解读(五) header和footer完善
- 二分 starway
- java大神给初学者的建议 发展方向
- number类型
- C++ 引用调用
- 各版本浏览器兼容性的写法
- 批处理--未写完,很抱歉大家点进来
- 宏基因组分析实战教程1. 背景知识
- 大话设计模式----策略模式