1.先构建WrapRecyclerAdapter
/** * Description: 可以添加头部和底部的Adapter */ public class WrapRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private final static String TAG = "WrapRecyclerAdapter"; /** * SparseArrays map integers to Objects. Unlike a normal array of Objects, * there can be gaps in the indices. It is intended to be more memory efficient * than using a HashMap to map Integers to Objects, both because it avoids * auto-boxing keys and its data structure doesn't rely on an extra entry object * for each mapping. * * SparseArray是一个<int , Object>的HashMap 比HashMap更高效 */ private SparseArray<View> mHeaderViews; private SparseArray<View> mFooterViews; // 基本的头部类型开始位置 用于viewType private static int BASE_ITEM_TYPE_HEADER = 10000000; // 基本的底部类型开始位置 用于viewType private static int BASE_ITEM_TYPE_FOOTER = 20000000; /** * 数据列表的Adapter */ private RecyclerView.Adapter mAdapter; public WrapRecyclerAdapter(RecyclerView.Adapter adapter) { this.mAdapter = adapter; mHeaderViews = new SparseArray<>(); mFooterViews = new SparseArray<>(); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // viewType 可能就是 SparseArray 的key if (isHeaderViewType(viewType)) { View headerView = mHeaderViews.get(viewType); return createHeaderFooterViewHolder(headerView); } if (isFooterViewType(viewType)) { View footerView = mFooterViews.get(viewType); return createHeaderFooterViewHolder(footerView); } return mAdapter.onCreateViewHolder(parent, viewType); } /** * 是不是底部类型 */ private boolean isFooterViewType(int viewType) { int position = mFooterViews.indexOfKey(viewType); return position >= 0; } /** * 创建头部或者底部的ViewHolder */ private RecyclerView.ViewHolder createHeaderFooterViewHolder(View view) { return new RecyclerView.ViewHolder(view) { }; } /** * 是不是头部类型 */ private boolean isHeaderViewType(int viewType) { int position = mHeaderViews.indexOfKey(viewType); return position >= 0; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (isHeaderPosition(position) || isFooterPosition(position)) { return; } // 计算一下位置 final int adapterPosition = position - mHeaderViews.size(); mAdapter.onBindViewHolder(holder, adapterPosition); // 设置点击和长按事件 if (mItemClickListener != null) { holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mItemClickListener.onItemClick(v, adapterPosition); } }); } if (mLongClickListener != null) { holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { return mLongClickListener.onLongClick(v, adapterPosition); } }); } } @Override public int getItemViewType(int position) { if (isHeaderPosition(position)) { // 直接返回position位置的key return mHeaderViews.keyAt(position); } if (isFooterPosition(position)) { // 直接返回position位置的key position = position - mHeaderViews.size() - mAdapter.getItemCount(); return mFooterViews.keyAt(position); } // 返回列表Adapter的getItemViewType 117 position = position - mHeaderViews.size(); return mAdapter.getItemViewType(position); } /** * 是不是底部位置 */ private boolean isFooterPosition(int position) { return position >= (mHeaderViews.size() + mAdapter.getItemCount()); } /** * 是不是头部位置 */ private boolean isHeaderPosition(int position) { return position < mHeaderViews.size(); } @Override public int getItemCount() { // 条数三者相加 = 底部条数 + 头部条数 + Adapter的条数 return mAdapter.getItemCount() + mHeaderViews.size() + mFooterViews.size(); } /** * 获取列表的Adapter */ private RecyclerView.Adapter getAdapter() { return mAdapter; } // 添加头部 public void addHeaderView(View view) { int position = mHeaderViews.indexOfValue(view); if (position < 0) { mHeaderViews.put(BASE_ITEM_TYPE_HEADER++, view); } notifyDataSetChanged(); } // 添加底部 public void addFooterView(View view) { int position = mFooterViews.indexOfValue(view); if (position < 0) { mFooterViews.put(BASE_ITEM_TYPE_FOOTER++, view); } notifyDataSetChanged(); } // 移除头部 public void removeHeaderView(View view) { int index = mHeaderViews.indexOfValue(view); if (index < 0) return; mHeaderViews.removeAt(index); notifyDataSetChanged(); } // 移除底部 public void removeFooterView(View view) { int index = mFooterViews.indexOfValue(view); if (index < 0) return; mFooterViews.removeAt(index); notifyDataSetChanged(); } /** * 解决GridLayoutManager添加头部和底部不占用一行的问题 * * @param recycler * @version 1.0 */ public void adjustSpanSize(RecyclerView recycler) { if (recycler.getLayoutManager() instanceof GridLayoutManager) { final GridLayoutManager layoutManager = (GridLayoutManager) recycler.getLayoutManager(); layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { boolean isHeaderOrFooter = isHeaderPosition(position) || isFooterPosition(position); return isHeaderOrFooter ? layoutManager.getSpanCount() : 1; } }); } } /*************** * 给条目设置点击和长按事件 *********************/ 205 public OnItemClickListener mItemClickListener; public OnLongClickListener mLongClickListener; public void setOnItemClickListener(OnItemClickListener itemClickListener) { this.mItemClickListener = itemClickListener; } public void setOnLongClickListener(OnLongClickListener longClickListener) { this.mLongClickListener = longClickListener; } }
2.构建WrapRecyclerView
我们最好还是模仿ListView的结构搞就搞到西,自定义一个WrapRecyclerView,可以添加删除头部和底部View,这个就比较简单
/** * Description: 可以添加头部和底部的RecyclerView */ public class WrapRecyclerView extends RecyclerView { // 包裹了一层的头部底部Adapter private WrapRecyclerAdapter mWrapRecyclerAdapter; // 这个是列表数据的Adapter private Adapter mAdapter; // 增加一些通用功能 // 空列表数据应该显示的空View // 正在加载数据页面,也就是正在获取后台接口页面 private View mEmptyView, mLoadingView; public WrapRecyclerView(Context context) { super(context); } public WrapRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public WrapRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void setAdapter(Adapter adapter) { // 为了防止多次设置Adapter if (mAdapter != null) { mAdapter.unregisterAdapterDataObserver(mDataObserver); mAdapter = null; } this.mAdapter = adapter; if (adapter instanceof WrapRecyclerAdapter) { mWrapRecyclerAdapter = (WrapRecyclerAdapter) adapter; } else { mWrapRecyclerAdapter = new WrapRecyclerAdapter(adapter); } super.setAdapter(mWrapRecyclerAdapter); // 注册一个观察者 mAdapter.registerAdapterDataObserver(mDataObserver); // 解决GridLayout添加头部和底部也要占据一行 mWrapRecyclerAdapter.adjustSpanSize(this); // 加载数据页面 if (mLoadingView != null && mLoadingView.getVisibility() == View.VISIBLE) { mLoadingView.setVisibility(View.GONE); } if (mItemClickListener != null) { mWrapRecyclerAdapter.setOnItemClickListener(mItemClickListener); } if (mLongClickListener != null) { mWrapRecyclerAdapter.setOnLongClickListener(mLongClickListener); } } // 添加头部 public void addHeaderView(View view) { // 如果没有Adapter那么就不添加,也可以选择抛异常提示 // 让他必须先设置Adapter然后才能添加,这里是仿照ListView的处理方式 if (mWrapRecyclerAdapter != null) { mWrapRecyclerAdapter.addHeaderView(view); } } // 添加底部 public void addFooterView(View view) { if (mWrapRecyclerAdapter != null) { mWrapRecyclerAdapter.addFooterView(view); } } // 移除头部 public void removeHeaderView(View view) { if (mWrapRecyclerAdapter != null) { mWrapRecyclerAdapter.removeHeaderView(view); } } // 移除底部 public void removeFooterView(View view) { if (mWrapRecyclerAdapter != null) { mWrapRecyclerAdapter.removeFooterView(view); } } private AdapterDataObserver mDataObserver = new AdapterDataObserver() { @Override public void onChanged() { if (mAdapter == null) return; // 观察者 列表Adapter更新 包裹的也需要更新不然列表的notifyDataSetChanged没效果 if (mWrapRecyclerAdapter != mAdapter) mWrapRecyclerAdapter.notifyDataSetChanged(); dataChanged(); } @Override public void onItemRangeRemoved(int positionStart, int itemCount) { if (mAdapter == null) return; // 观察者 列表Adapter更新 包裹的也需要更新不然列表的notifyDataSetChanged没效果 if (mWrapRecyclerAdapter != mAdapter) mWrapRecyclerAdapter.notifyItemRemoved(positionStart); dataChanged(); } @Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { if (mAdapter == null) return; // 观察者 列表Adapter更新 包裹的也需要更新不然列表的notifyItemMoved没效果 if (mWrapRecyclerAdapter != mAdapter) mWrapRecyclerAdapter.notifyItemMoved(fromPosition, toPosition); dataChanged(); } @Override public void onItemRangeChanged(int positionStart, int itemCount) { if (mAdapter == null) return; // 观察者 列表Adapter更新 包裹的也需要更新不然列表的notifyItemChanged没效果 if (mWrapRecyclerAdapter != mAdapter) mWrapRecyclerAdapter.notifyItemChanged(positionStart); dataChanged(); } @Override public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { if (mAdapter == null) return; // 观察者 列表Adapter更新 包裹的也需要更新不然列表的notifyItemChanged没效果 if (mWrapRecyclerAdapter != mAdapter) mWrapRecyclerAdapter.notifyItemChanged(positionStart, payload); dataChanged(); } @Override public void onItemRangeInserted(int positionStart, int itemCount) { if (mAdapter == null) return; // 观察者 列表Adapter更新 包裹的也需要更新不然列表的notifyItemInserted没效果 if (mWrapRecyclerAdapter != mAdapter) mWrapRecyclerAdapter.notifyItemInserted(positionStart); dataChanged(); } }; /** * 添加一个空列表数据页面 */ 155 public void addEmptyView(View emptyView) { this.mEmptyView = emptyView; } /** * 添加一个正在加载数据的页面 */ public void addLoadingView(View loadingView) { this.mLoadingView = loadingView; mLoadingView.setVisibility(View.VISIBLE); } /** * Adapter数据改变的方法 */ private void dataChanged() { if (mAdapter.getItemCount() == 0) { // 没有数据 if (mEmptyView != null) { mEmptyView.setVisibility(VISIBLE); } } else { // 没有数据 if (mEmptyView != null) { mEmptyView.setVisibility(GONE); } } } /*************** * 给条目设置点击和长按事件 *********************/ public com.zzw.framelibray.recyclerview.adapter.OnItemClickListener mItemClickListener; public com.zzw.framelibray.recyclerview.adapter.OnLongClickListener mLongClickListener; public void setOnItemClickListener(com.zzw.framelibray.recyclerview.adapter.OnItemClickListener itemClickListener) { this.mItemClickListener = itemClickListener; if (mWrapRecyclerAdapter != null) { mWrapRecyclerAdapter.setOnItemClickListener(mItemClickListener); } } public void setOnLongClickListener(com.zzw.framelibray.recyclerview.adapter.OnLongClickListener longClickListener) { this.mLongClickListener = longClickListener; if (mWrapRecyclerAdapter != null) { mWrapRecyclerAdapter.setOnLongClickListener(mLongClickListener); } } }
3.使用:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <com.zzw.framelibray.recyclerview.view.WrapRecyclerView android:id="@+id/wrap_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Activity
public class HeaderFooterActivity extends AppCompatActivity implements OnItemClickListener { private WrapRecyclerView mRecyclerView; private List<People> mData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recycler_view); mRecyclerView = (WrapRecyclerView) findViewById(R.id.wrap_recycler_view); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mData =new ArrayList<>(); mData.add(new People()); mData.add(new People()); mData.add(new People()); PeopleListAdapter listAdapter = new PeopleListAdapter(this, mData); // 添加头部和底部 需要 包裹Adapter,才能添加头部和底部 WrapRecyclerAdapter wrapRecyclerAdapter = new WrapRecyclerAdapter(listAdapter); mRecyclerView.setAdapter(wrapRecyclerAdapter); wrapRecyclerAdapter.setOnItemClickListener(this); // 添加头部和底部 wrapRecyclerAdapter.addHeaderView(LayoutInflater.from(this).inflate(R.layout.layout_header,mRecyclerView,false)); wrapRecyclerAdapter.addFooterView(LayoutInflater.from(this).inflate(R.layout.layout_header,mRecyclerView,false)); } @Override public void onItemClick(View view, int position) { Toast.makeText(this, "" + mData.get(position).name, Toast.LENGTH_SHORT).show(); } class PeopleListAdapter extends CommonRecyclerAdapter<People> { public PeopleListAdapter(Context context, List<People> datas) { super(context, datas, R.layout.channel_list_item); } @Override public void convert(ViewHolder holder, People item, int position) { holder.setText(R.id.action_btn, item.name+position); } } class People{ String name="王伟:"; } }
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/aiops/3091.html