以前寫過一篇關(guān)于RecyclerView的頭部尾部的添加
也有一個(gè)Demo 不過Linear Grid Stagge三個(gè)是分開的 如下圖1 今天的是一個(gè)整合的DRecyclerView 如下圖二 講一下實(shí)現(xiàn)過程

這是整合的 使用更加方便

先看效果圖

- 首先來分析最簡(jiǎn)單的 也就是LinearLayoutManager情況下的 添加頭部 尾部 和中間插入
在繼承RecyclerView的使用中 兩個(gè)關(guān)鍵方法
onCreateViewHolder 和 onBindViewHolder
onCreateViewHolder 創(chuàng)建布局View
onBindViewHolder 綁定數(shù)據(jù)
所以我們要在顯示不同的布局上做處理 就只能在 onCreateViewHolder 創(chuàng)建的時(shí)候做處理
觀察 onCreateViewHolder 這個(gè)方法 通過該方法參數(shù)
onCreateViewHolder(ViewGroup parent, int viewType) {---}
發(fā)現(xiàn) 我們能做處理的 只有viewType 這個(gè)字段 看字面意思也能猜到是不同view的類型
然后我們看源碼


然后 getItemType(int position) 這個(gè)方法上面說了 用來返回不同的View的type 也就是說 onCreateViewHolder中的ViewType來自這個(gè)方法 默認(rèn)是返回0 我們?cè)谧约旱奶幚碇兄貙戇@個(gè)方法就行了
我們就返回 當(dāng)前進(jìn)來的position

然后在onCreateViewHolder中自己處理
好 現(xiàn)在在分析 整個(gè)類 要具備的一些條件
一個(gè)HeadViews 的集合 緩存所有的HeadView
一個(gè)FootViews的集合 緩存所有的FootView
一個(gè)中間插入的View的 集合 緩存所有的插入View[這個(gè)View就是數(shù)據(jù)列表中不同的類型做不同的布局 一般滑動(dòng)很多顯示一個(gè) 推薦 等等]
整個(gè)DRecyclerViewAdapater 代碼如下
public class DRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static final String Tag = DRecyclerViewAdapter.class.getName();
private RecyclerView.Adapter mInnerAdapter;
public DRecyclerViewAdapter(DBaseRecyclerViewAdapter adapter) {
setAdapter(adapter);
}
public void setAdapter(DBaseRecyclerViewAdapter myAdapter) {
if (myAdapter != null) {
if (!(myAdapter instanceof RecyclerView.Adapter))
throw new RuntimeException("your adapter must be a RecyclerView.Adapter");
}
this.mInnerAdapter = myAdapter;
myAdapter.setDRecyclerViewAdapter(this);
}
/**
* head foot list cache
*/
private List<View> mHeadViews = new ArrayList<View>();
private List<View> mFootViews = new ArrayList<View>();
private List<View> mRandomViews = new ArrayList<View>();
private SparseArray<Integer> mRandomViews_position = new SparseArray<Integer>();
/**
* addHead to recyclerview
*
* @param view
*/
public void addHeadView(View view) {
mHeadViews.add(view);
}
/**
* addFoot to RecyclerView
*
* @param view
*/
public void addFootView(View view) {
mFootViews.add(view);
}
/**
* 使用一次 存下來 后續(xù) 好查找
*/
private int index=0;
public void addRandomView(View view, int posistion) {
mRandomViews_position.append(posistion,index);
index++;
mRandomViews.add(view);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
DRecyclerViewHolder dRecyclerViewHolder;
Log.e(Tag, "當(dāng)前type " + viewType);
if (viewType < mHeadViews.size()) {
Log.e(Tag, "headView" + viewType);
return new DRecyclerViewHolder(mHeadViews.get(viewType));
} else if (viewType >= mHeadViews.size() && viewType < mHeadViews.size() + mInnerAdapter.getItemCount()) {
if (mRandomViews_position.get(viewType - mHeadViews.size())!=null) {
View view = mRandomViews.get(mRandomViews_position.get(viewType - mHeadViews.size()));
return new DRecyclerViewHolder(view);
}
return mInnerAdapter.onCreateViewHolder(parent, viewType - mHeadViews.size());
} else {
Log.e(Tag, "FootView" + viewType);
int position = viewType - mHeadViews.size() - mInnerAdapter.getItemCount();
if (position >= 0 && position < mFootViews.size()) {
return new DRecyclerViewHolder(mFootViews.get(position));
} else {
return null;
}
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (position >= mHeadViews.size() && position < mHeadViews.size() + mInnerAdapter.getItemCount()) {
//不包括那些插入的
if (mRandomViews_position.get(position - mHeadViews.size())==null)
mInnerAdapter.onBindViewHolder(holder, position - mHeadViews.size());
} else {
/**
* 瀑布流的設(shè)置處理
*/
ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
if (layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
((StaggeredGridLayoutManager.LayoutParams) layoutParams).setFullSpan(true);
}
}
}
@Override
public int getItemCount() {
return mHeadViews.size() + mInnerAdapter.getItemCount() + mFootViews.size();
}
@Override
public int getItemViewType(int position) {
return position;
}
public int getFootSize() {
return mFootViews.size();
}
public int getHeadSize() {
return mHeadViews.size();
}
public boolean isHeader(int position) {
return position < mHeadViews.size() ? true : false;
}
public boolean isFooter(int position) {
return position >= mHeadViews.size() + mInnerAdapter.getItemCount() ? true : false;
}
public boolean isRandom(int position){
Log.e("isRandom",position+" "+mRandomViews_position.get(position-mHeadViews.size()));
return mRandomViews_position.get(position-mHeadViews.size())!=null?true:false;
}
static class DRecyclerViewHolder extends RecyclerView.ViewHolder {
public DRecyclerViewHolder(View itemView) {
super(itemView);
}
}
}
可以看到 邏輯處理在onCreateViewHolder中
根據(jù)進(jìn)來的ViewType 也就是position
整套羅不難 就是根據(jù)position的位置來區(qū)分來區(qū)分屬于哪個(gè)地方的View
mRandomViews_position 這個(gè)是處理中間數(shù)據(jù)不同的記錄 用的SparseArray 類似Map 效率高些 節(jié)約內(nèi)存 查找內(nèi)部二分查找 不多介紹
目的是 記錄 列表數(shù)據(jù)中的 那些位置是插入的 不同的View
上面是LinearLayoutManager的情況 屬于最簡(jiǎn)單的情況
分析一下GridLayoutManager 這個(gè) 主要方法就是 這個(gè)方法 源碼里面有

設(shè)置每個(gè)Item 所占得位置 默認(rèn)是1 如果你的2列 這里可以在添加頭部的時(shí)候 設(shè)置為2 就會(huì)占一整行了
所以 封裝一個(gè) 類 繼承GridLayoutManager.SpanSizeLookup 是頭部 尾部 插入位置 都占用一個(gè)大格
/**
* Created by Daemon on 2015/11/10.
*/
public class DSpanSizeLookup extends GridLayoutManager.SpanSizeLookup {
private DRecyclerViewAdapter adapter;
private int mSpanSize = 1;
public DSpanSizeLookup(DRecyclerViewAdapter adapter, int spanSize) {
this.adapter = adapter;
this.mSpanSize = spanSize;
}
@Override
public int getSpanSize(int position) {
boolean isHeaderOrFooterOrRandom = adapter.isHeader(position) || adapter.isFooter(position)
|| adapter.isRandom(position);
return isHeaderOrFooterOrRandom ? mSpanSize : 1;
}
}
所以在使用的時(shí)候 設(shè)置這個(gè)就行了 其余的不變
在看看 StaggeredGridLayoutManager 這里就要用到
LayoutParams lp = (LayoutParams)
view.getLayoutParams();lp.setFullSpan(true);
這種方法 來設(shè)置 不同的占用列數(shù) 重寫onMeasure方法 處理

這樣就是整個(gè)的使用原理
至于其中的DBaseRecyclerViewAdapter DBaseRecyclerViewHolder 等等都是一些輔助類 更加方便使用 和添加頭部 尾部 沒得啥具體關(guān)系 不介紹了
MainActivity的使用代碼
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private DRecyclerViewAdapter dRecyclerViewAdapter;
private LinearLayoutManager linearLayoutManager;
private Button bt_linear;
private Button bt_grid;
private Button bt_stagge;
private MyAdpater myAdpater;
private GridLayoutManager gridLayoutManager;
private DStaggeredGridLayoutManager staggeLayoutManager;
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_linear:
if (linearLayoutManager == null) {
linearLayoutManager = new LinearLayoutManager(MainActivity.this);
}
rcv_list.setLayoutManager(linearLayoutManager);
dRecyclerViewAdapter.notifyDataSetChanged();
rcv_list.addOnScrollListener(new DRecyclerViewScrollListener() {
@Override
public void onLoadNextPage(RecyclerView view) {
Toast.makeText(MainActivity.this,"底部",Toast.LENGTH_SHORT).show();
}
});
break;
case R.id.bt_grid:
if (gridLayoutManager == null) {
gridLayoutManager = new GridLayoutManager(MainActivity.this, 2);
gridLayoutManager.setSpanSizeLookup(new DSpanSizeLookup(dRecyclerViewAdapter, gridLayoutManager.getSpanCount()));
}
rcv_list.setLayoutManager(gridLayoutManager);
dRecyclerViewAdapter.notifyDataSetChanged();
rcv_list.addOnScrollListener(new DRecyclerViewScrollListener() {
@Override
public void onLoadNextPage(RecyclerView view) {
Toast.makeText(MainActivity.this,"底部",Toast.LENGTH_SHORT).show();
}
});
break;
case R.id.bt_stagge:
Intent intent=new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent);
break;
}
}
private RecyclerView rcv_list;
private List<Data> list;
public static class Data{
public String value;
public int type;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rcv_list = (RecyclerView) findViewById(R.id.rcv_list);
bt_linear = (Button) findViewById(R.id.bt_linear);
bt_grid = (Button) findViewById(R.id.bt_grid);
bt_stagge = (Button) findViewById(R.id.bt_stagge);
list = new ArrayList<Data>();
bt_linear.setOnClickListener(this);
bt_grid.setOnClickListener(this);
bt_stagge.setOnClickListener(this);
for (int i = 0; i < 20; i++) {
Data data=new Data();
data.value="Daemon data " + i;
data.type=0;
list.add(data);
//一種判斷標(biāo)示 可以根據(jù)實(shí)際需求來做標(biāo)識(shí)
if (i % 5 == 0) {
data.type=1;
}
}
myAdpater = new MyAdpater(list, this);
dRecyclerViewAdapter = new DRecyclerViewAdapter(myAdpater);
linearLayoutManager = new LinearLayoutManager(MainActivity.this);
rcv_list.setLayoutManager(linearLayoutManager);
addHeadViews();
addFootviews();
addRandomView();
myAdpater.setOnClickItemListsner(new DBaseRecyclerViewAdapter.OnClickItemListsner() {
@Override
public void onClick(int poisiton) {
Toast.makeText(MainActivity.this, poisiton + "", Toast.LENGTH_SHORT).show();
}
});
rcv_list.setAdapter(dRecyclerViewAdapter);
rcv_list.addOnScrollListener(new DRecyclerViewScrollListener() {
@Override
public void onLoadNextPage(RecyclerView view) {
Toast.makeText(MainActivity.this,"底部",Toast.LENGTH_SHORT).show();
}
});
}
/**
* 添加全部的Views 中間插入的廣告欄 等等
*/
private void addRandomView() {
for(int i=0 ; i<list.size();i++){
if(list.get(i).type==1){
View view = LayoutInflater.from(this).inflate(R.layout.random_item, rcv_list, false);
dRecyclerViewAdapter.addRandomView(view,i);
}
}
}
/**
* add HeadView
*/
private void addHeadViews() {
View head = LayoutInflater.from(this).inflate(R.layout.head, rcv_list, false);
View head1 = LayoutInflater.from(this).inflate(R.layout.head, rcv_list, false);
dRecyclerViewAdapter.addHeadView(head);
dRecyclerViewAdapter.addHeadView(head1);
}
/**
* add Footview
*/
private void addFootviews() {
View foot = LayoutInflater.from(this).inflate(R.layout.foot, rcv_list, false);
View foot1 = LayoutInflater.from(this).inflate(R.layout.foot, rcv_list, false);
dRecyclerViewAdapter.addFootView(foot);
dRecyclerViewAdapter.addFootView(foot1);
}
/**
* 繼承封裝過的DBaseRecyclerViewAdapter
*/
class MyAdpater extends DBaseRecyclerViewAdapter<Data> {
public MyAdpater(List<Data> mDatas, Context mContext) {
super(mDatas, mContext);
}
@Override
protected DBaseRecyclerViewHolder onCreateViewHolder1(ViewGroup parent, int viewType) {
return new MyViewHoder(parent, R.layout.item, this);
}
}
/**
* 繼承封裝過的 DBaseRecyclerViewHolder
*/
class MyViewHoder extends DBaseRecyclerViewHolder<Data> implements View.OnClickListener {
private TextView tv_content;
public MyViewHoder(ViewGroup parent, @LayoutRes int res, DBaseRecyclerViewAdapter dBaseRecyclerViewAdapter) {
super(parent, res, dBaseRecyclerViewAdapter);
tv_content = $(R.id.tv_content);
itemView.setOnClickListener(this);
}
@Override
public void setData(Data data, int position) {
//每次默認(rèn)初始化 因?yàn)镾tagge會(huì)改變高度
ViewGroup.LayoutParams layoutParams1 = tv_content.getLayoutParams();
layoutParams1.height = 80;
tv_content.setLayoutParams(layoutParams1);
tv_content.setText(data.value);
}
@Override
public void onClick(View v) {
if (getOnClickItemListsner() != null) {
getOnClickItemListsner().onClick(getAdapterItemPosition());
}
}
}
}
放在Github上面 整個(gè)Demo