test.jpg
添加頭布局和腳步:
只要是用過RecyclerView的估計大家都知道,這個東西不像ListView那樣直接可以
- addHeaderView()或addFooterView(),removeHeaderView(),removeFooterView()
所以今天就進入我們的正題,一千人就有一千個哈姆雷特,給RecyclerView添加頭的方式各有各的方式:就我目前所見:基本類似就是三種: - 上邊用一個垂直的LinearLayout 里面動態的添加或者移除l
- 模仿ListView的添加頭的方法,如果是這種就要去看ListView的源碼了,不過我覺得這種添加方式不是特別好,只是個人建議,因為你還得去重寫recyclerview,感覺還是稍稍的的有嗲麻煩
- 第三種,也是我接下我要寫的這一種裝飾者模式添加頭,給這個對象額外的增加功能:
一不開心就上代碼:
/**
* Created by fx on 2017/6/29.
* 采用裝飾著模式進行封裝頭部和尾部:
*/
public class HeaderAndFooterWrapper<k> extends RecyclerView.Adapter<BaseViewHolder> {
private static final int BASE_ITEM_TYPE_HEADER = 100000;
private static final int BASE_ITEM_TYPE_FOOTER = 200000;
private SparseArray<View> mHeaderViews = new SparseArray<>();
private SparseArray<View> mFootViews = new SparseArray<>();
private BaseAdapter<k> mInnerAdapter;
private static final int M_DEFAULT_NUMBER = -1;
private static final String TAG = "HeaderAndFooterWrapper";
//將我們自己的adapter 傳進去:
public HeaderAndFooterWrapper(BaseAdapter<k> adapter) {
mInnerAdapter = adapter;
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
BaseViewHolder holder;
if (mHeaderViews.get(viewType) != null) {
holder = BaseViewHolder.creatBaseViewHolder(mHeaderViews.get(viewType));
return holder;
} else if (mFootViews.get(viewType) != null) {
holder = BaseViewHolder.creatBaseViewHolder(mFootViews.get(viewType));
return holder;
}
return mInnerAdapter.onCreateViewHolder(parent, viewType);
}
@Override
public void onBindViewHolder(BaseViewHolder viewHolder, int position) {
if (isHeaderViewPos(position)) {
return;
}
if (isFooterViewPos(position)) {
return;
}
mInnerAdapter.onBindViewHolder(viewHolder, position - getHeadersCount());
}
@Override
public int getItemViewType(int position) {
if (isHeaderViewPos(position)) {
return mHeaderViews.keyAt(position);
} else if (isFooterViewPos(position)) {
return mFootViews.keyAt(position - getHeadersCount() - getRealItemCount());
}
return mInnerAdapter.getItemViewType(position - getHeadersCount());
}
private int getRealItemCount() {
return mInnerAdapter.getItemCount();
}
@Override
public int getItemCount() {
return getHeadersCount() + getFootersCount() + getRealItemCount();
}
private boolean isHeaderViewPos(int position) {
return position < getHeadersCount();
}
private boolean isFooterViewPos(int position) {
return position >= getHeadersCount() + getRealItemCount();
}
//add Headers 不重復添加頭布局:
public void addHeaderView(View view) {
int i = mHeaderViews.indexOfValue(view);
if (M_DEFAULT_NUMBER == i) {
mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER, view);
}
}
public void addFootView(View view) {
int i = mFootViews.indexOfValue(view);
if (M_DEFAULT_NUMBER == i) {
mFootViews.put(mFootViews.size() + BASE_ITEM_TYPE_FOOTER, view);
}
}
public int getHeadersCount() {
return mHeaderViews.size();
}
public int getFootersCount() {
return mFootViews.size();
}
//針對網格布局:
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
mInnerAdapter.onAttachedToRecyclerView(recyclerView);
final RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) {
((GridLayoutManager) manager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
//如果是頭布局或者是腳布局返回為1;
int itemViewType = getItemViewType(position);
if (mHeaderViews.get(itemViewType) != null || mFootViews.get(itemViewType) != null) {
return ((GridLayoutManager) manager).getSpanCount();
}
return 1;
}
});
}
}
//針對流式布局
@Override
public void onViewAttachedToWindow(BaseViewHolder holder) {
mInnerAdapter.onViewAttachedToWindow(holder);
int layoutPosition = holder.getLayoutPosition();
if (isHeaderViewPos(layoutPosition) || isFooterViewPos(layoutPosition)) {
ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
if (layoutParams != null) {
if (layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) layoutParams;
//占領全部空間;
params.setFullSpan(true);
}
}
}
}
//remover header;
public boolean removedHeader(View view) {
int i = mHeaderViews.indexOfValue(view);
if (i == M_DEFAULT_NUMBER ) {
return false;
}
mHeaderViews.removeAt(i);
notifyItemRemoved(i);
return true;
}
//remover footer
public boolean removedFooter(View view) {
int i = mFootViews.indexOfValue(view);
if (i == M_DEFAULT_NUMBER ) {
return false;
}
mFootViews.removeAt(i);
notifyItemRemoved(i);
return true;
}
//remover all footerview;
public boolean removerAllFooterView() {
if (mFootViews.size() > 0) {
mFootViews.clear();
notifyDataSetChanged();
return true;
}
return false;
}
//remover all footerview;
public boolean removerAllHeaderView() {
if (mHeaderViews.size() > 0) {
mHeaderViews.clear();
notifyDataSetChanged();
return true;
}
return false;
}
}
在Activity里面直接這樣使用
- 添加頭
ComAdapter comAdapter = new ComAdapter(C.getList());
View view = mInflate.inflate(R.layout.header_view, (ViewGroup) mRecyView.getParent(), false);
HeaderAndFooterWrapper<String> emptyViewAdapter = new HeaderAndFooterWrapper<String>(comAdapter);
emptyViewAdapter.addHeaderView(view);
emptyViewAdapter.addFootView(view);
mRecyView.setAdapter(emptyViewAdapter);
///new HeaderAndFooterWrapper() 將當前的comAdapter 傳入進去, 可以添加多個頭布局和腳布局:
- 移移除單個頭布局和單個腳布局
- removedHeader
- removedFooter
- 移除所有的頭布局和腳布局
- removerAllHeaderView
- removerAllFooterView
總結:
終于寫完了,是不是感覺用起來很簡單,像之前的ListView 一樣的 直接可以添加頭,移除頭 添加腳布局,移除腳布局;由于時間有限沒有錄gif視屏,后期一定補上, 廢話也就不多說了,如果大家覺得我寫的還不錯,就抬起手給點個贊唄,如果有更好的或者覺得寫的有問題的歡迎提問和騷擾
謝謝大家;