转载请标明出处:
http://blog.youkuaiyun.com/sinat_15877283/article/details/50913998;
本文出自: 【温利东的博客】
前言 FOREWORD
- 很多人(包括我)已经开始抛弃ListView和GridView转为RecyclerView了。
网络上有很多关于RecyclerView加头加尾的文章,其中组合模式占多,这种模式大概思路是自定义一个customView 然后在里面放置 一个头布局容器、一个尾布局容器,一个RecyclerView容器 :

这种写法太low了…..原本recyclerView层级就很深了,这相当于在加深了一层,碰上稍微复杂一些的item,手机不是要卡到爆吗?这让低端机怎么活!!!
- 最近在看《App研发录》这本书籍,感觉之前对recyclerView封装的不到位,借此完善一下。
正文 BODY
说说本篇文章需要解决的问题,了解需求我们才能有针对性的进行封装:
- 可为RecyclerView 添加/移除 多个Header和Footer
- 解决HeaderView、FooterView在网格/瀑布流中 布局不足一行问题
- 可拓展、低耦合
行为封装: IAdapter< VH, M>:
/**
* Created by wenld- on 2016/3/17.
*/
public interface IAdapter<VH, M> {
/** 设置 主内容 View类型 */
int getAdvanceViewType(int position);
/** 加头View */
void addHeaderView(View headerView);
/** 加尾View */
void addFooterView(View footerView);
/** 数据绑定View */
void onBindAdvanceViewHolder(VH holder, int i);
/** 加载 ViewGroup 容器 */
RecyclerView.ViewHolder onCreateAdvanceViewHolder(ViewGroup parent, int viewType);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
需要事先了解的技术点:
public int getItemViewType(int position) {...}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return (getItemViewType(position) % HeaderFooterFlag == 0)
? gridManager.getSpanCount() : 1;
}
});
}
}
@Override
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
super.onViewAttachedToWindow(holder);
ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
if (lp != null
&& lp instanceof StaggeredGridLayoutManager.LayoutParams
&& holder.getLayoutPosition() == 0) {
StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
p.setFullSpan(true);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 判断View类型: public int getItemViewType(int position)
- 让头尾View在 GridLayoutManager,StaggeredGridLayoutManager布局中 占用1行
封装篇 AdvancedAdapter:
public abstract class AdvancedAdapter<VH extends AdvancedAdapter.ViewHolder, M>
extends RecyclerView.Adapter<RecyclerView.ViewHolder>
implements IAdapter<VH, M> {
private ArrayList<View> mHeaderViews = new ArrayList<>();
private ArrayList<View> mFooterViews = new ArrayList<>();
protected ItemClickInterface<M> listener;
protected List<M> mData;
public final void addHeaderView(View headerView) {
mHeaderViews.add(headerView);
}
public final void addFooterView(View footerView) {
mFooterViews.add(footerView);
}
private SparseIntArray mHeaderViewTypes = new SparseIntArray();
private SparseIntArray mFooterViewTypes = new SparseIntArray();
private final static int HeaderFooterFlag = 100000;
@Override
public int getItemViewType(int position) {
if (mHeaderViews.size() > 0 && position < mHeaderViews.size()) {
position = (position + 1) * HeaderFooterFlag;
mHeaderViewTypes.put(position, position);
return position;
}
if (mFooterViews.size() > 0 && position > getAdvanceCount() - 1 + mHeaderViews.size()) {
position = (position + 1) * HeaderFooterFlag;
mHeaderViewTypes.put(position, position);
return position;
}
return getAdvanceViewType(position);
}
public int getAdvanceCount() {
int a = 0;
if (mData != null) {
a = mData.size();
}
return a;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mHeaderViewTypes.get(viewType, -1) != (-1)) {
return new HeaderHolder(mHeaderViews.get(viewType / 100000 - 1));
}
if (mFooterViewTypes.get(viewType, -1) != (-1)) {
int index = viewType / 100000 - 1 - getAdvanceCount() - mHeaderViews.size();
return new FooterHolder(mFooterViews.get(index));
}
return onCreateAdvanceViewHolder(parent, viewType);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (mFooterViews.size() > 0 && (position > getAdvanceCount() - 1 + mHeaderViews.size())) {
return;
}
if (mHeaderViews.size() > 0) {
if (position < mHeaderViews.size()) {
return;
}
onBindAdvanceViewHolder((VH) holder, position - mHeaderViews.size());
return;
}
onBindAdvanceViewHolder((VH) holder, position - mHeaderViews.size());
}
class HeaderHolder extends RecyclerView.ViewHolder {
public HeaderHolder(View itemView) {
super(itemView);
}
}
class FooterHolder extends RecyclerView.ViewHolder {
public FooterHolder(View itemView) {
super(itemView);
}
}
public abstract class ViewHolder extends RecyclerView.ViewHolder implements IViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
public int getAdpPosition() {
return Selected(getAdapterPosition());
}
}
public M getItem(int position) {
if (getItemCount() == 0) {
return null;
}
return mData.get(position);
}
@Override
public int getItemCount() {
if (mHeaderViews.size() > 0 && mFooterViews.size() > 0) {
return getAdvanceCount() + mHeaderViews.size() + mFooterViews.size();
}
if (mHeaderViews.size() > 0) {
return getAdvanceCount() + mHeaderViews.size();
}
if (mFooterViews.size() > 0) {
return getAdvanceCount() + mFooterViews.size();
}
return getAdvanceCount();
}
public int Selected(int position) {
if (mHeaderViews.size() > 0 && position < mHeaderViews.size()) {
return -1;
}
if (mFooterViews.size() > 0 && position > getAdvanceCount() - 1 + mHeaderViews.size()) {
return -1;
} else {
return position - mHeaderViews.size();
}
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return (getItemViewType(position) % HeaderFooterFlag == 0)
? gridManager.getSpanCount() : 1;
}
});
}
}
@Override
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
super.onViewAttachedToWindow(holder);
ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
if (lp != null
&& lp instanceof StaggeredGridLayoutManager.LayoutParams
&& holder.getLayoutPosition() == 0) {
StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
p.setFullSpan(true);
}
}
@Override
public void setData(List<M> mDataList) {
this.mData = mDataList;
}
@Override
public List<M> getData() {
return mData;
}
@Override
public void setListener(ItemClickInterface<M> listener) {
this.listener = listener;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
使用篇:MyAdapter:
public class MyAdapter extends AdvancedAdapter<ImageListAdapter.ViewHolder, ImagesListEntity> {
private Context mContext;
@Override
public int getAdvanceViewType(int position) {
return position;
}
@Override
public void onBindAdvanceViewHolder(ViewHolder holder, int i) {
.....
}
@Override
public RecyclerView.ViewHolder onCreateAdvanceViewHolder(ViewGroup parent, int viewType) {
ViewHolder vh = .....
return vh;
}
public MyAdapter (Context mContext, List<ImagesListEntity> mData, ItemClickInterface listener) {
...
}
public class ViewHolder extends AdvancedAdapter.ViewHolder {
public ImageView icon;
public ViewHolder(View v) {
super(v);
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
listener.onItemClick(mData.get(getAdpPosition()), getAdpPosition());
}
}
});
icon = (ImageView) v.findViewById(R.id.list_item_images_list_image);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
结论
样式做的不好看,但这不是重点…..(哈哈哈哈,随手加了一个TextView)

对于控件类的封装最好不要用组合模式!!!
对于控件类的封装最好不要用组合模式!!!
对于控件类的封装最好不要用组合模式!!!
重要的事情说三遍………
demo 戳这里、戳!戳!戳!
希望我的分享能对你有帮助,也希望你能提出你的意见和想法,一起分享,共同成长。
转载请标明出处: http://blog.youkuaiyun.com/sinat_15877283/article/details/50913998;