一个精简的实现RecyclerView可添加header和footer的Demo
来源:互联网 发布:美国国父路易十六知乎 编辑:程序博客网 时间:2024/06/05 20:44
一个精简的实现RecyclerView可添加header和footer的Demo
实现思路很简单,就是把用户设置给RecyclerView的Adapter进行再封装,封装的内部类ExtraItemAdapter负责管理用户添加的header和footer。
在onBind等方法中计算出偏移后的position再调用用户设置的原生adapter。
public class MyRecyclerView extends RecyclerView { protected ArrayList<View> mHeaderViews = new ArrayList<>(); protected ArrayList<View> mFooterViews = new ArrayList<>(); public MyRecyclerView(Context context) { super(context); } public MyRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public MyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void setAdapter(@NonNull Adapter adapter) { super.setAdapter(new ExtraItemAdpater(adapter)); } public void addHeaderView(@NonNull View headerView) { addHeaderView(mHeaderViews.size(), headerView); } public void addHeaderView(int index, @NonNull View headerView) { if (index >= 0 && index <= mHeaderViews.size()) { mHeaderViews.add(index, headerView); if (getAdapter() != null) { getAdapter().notifyItemInserted(index); } } } public void removeHeaderView(@NonNull View headerView) { int index = mHeaderViews.indexOf(headerView); if (index != -1) { mHeaderViews.remove(index); if (getAdapter() != null) { getAdapter().notifyItemRemoved(index); } } } public void addFooterView(@NonNull View footerView) { addFooterView(mFooterViews.size(), footerView); } public void addFooterView(int index, @NonNull View footerView) { if (index >= 0 && index <= mFooterViews.size()) { mFooterViews.add(index, footerView); if (getAdapter() != null) { getAdapter().notifyItemInserted(mHeaderViews.size() + ((ExtraItemAdpater)getAdapter()).getNormaItemNum() + index); } } } public void removeFooterView(@NonNull View footerView) { int index = mFooterViews.indexOf(footerView); if (index != -1) { mFooterViews.remove(index); if (getAdapter() != null) { getAdapter().notifyItemRemoved(getAdapter().getItemCount() - mFooterViews.size() + index); } } } public int getHeaderViewsCount() { return mHeaderViews.size(); } public int getFooterViewsCount() { return mFooterViews.size(); } private class ExtraItemAdpater extends Adapter { private Adapter mAdapter; public ExtraItemAdpater(Adapter adapter) { this.mAdapter = adapter; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == Integer.MAX_VALUE) { return new ExtraViewHolder(new FrameLayout(parent.getContext())); } return mAdapter.onCreateViewHolder(parent, viewType); } @Override public void onBindViewHolder(ViewHolder holder, int position) { if (position >= mHeaderViews.size() && position < (getItemCount() - mFooterViews.size())) { mAdapter.onBindViewHolder(holder, position - mHeaderViews.size()); } else { bindExtraViewHolder(holder, position); } } @Override public int getItemCount() { return mHeaderViews.size() + mFooterViews.size() + getNormaItemNum(); } @Override public int getItemViewType(int position) { if (position >= mHeaderViews.size() && position < (getItemCount() - mFooterViews.size())) { return mAdapter.getItemViewType(position - mHeaderViews.size()); } return Integer.MAX_VALUE; } @Override public void registerAdapterDataObserver(AdapterDataObserver observer) { if(this.mAdapter != null) { this.mAdapter.registerAdapterDataObserver(observer); } super.registerAdapterDataObserver(observer); } @Override public void unregisterAdapterDataObserver(AdapterDataObserver observer) { if(this.mAdapter != null) { this.mAdapter.unregisterAdapterDataObserver(observer); } super.unregisterAdapterDataObserver(observer); } public int getNormaItemNum() { return mAdapter.getItemCount(); } } public class ExtraViewHolder extends ViewHolder { public ExtraViewHolder(View itemView) { super(itemView); } } private void bindExtraViewHolder(ViewHolder holder, int position) { ExtraViewHolder extraViewHolder = (ExtraViewHolder) holder; FrameLayout itemContainer = (FrameLayout) extraViewHolder.itemView; View extraView; if (position < mHeaderViews.size()) { extraView = mHeaderViews.get(position); } else { int index = position - mHeaderViews.size() - ((ExtraItemAdpater)getAdapter()).getNormaItemNum(); extraView = mFooterViews.get(index); } // 防止复用item造成view重复添加 itemContainer.removeAllViews(); ViewGroup parentView = (ViewGroup) extraView.getParent(); if (parentView != null) { parentView.removeAllViews(); } itemContainer.addView(extraView); // 让header和footer的LayoutParams兼容不同的布局,目前只考虑瀑布流布局 ViewGroup.LayoutParams lp = itemContainer.getLayoutParams(); if (lp == null) { lp = MyRecyclerView.this.generateDefaultLayoutParams(); itemContainer.setLayoutParams(lp); } if (lp instanceof StaggeredGridLayoutManager.LayoutParams) { ((StaggeredGridLayoutManager.LayoutParams) lp).setFullSpan(true); } }}
附加测试用的Adapter类
public class RVAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ private final int NORMAL_ITEM_SIZE = 10; private final int TYPE_NORMAL = 0; private LayoutInflater mLayoutInflater; public RVAdapter(Context context){ mLayoutInflater = LayoutInflater.from(context); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { case TYPE_NORMAL : { return new NormalItemVH(mLayoutInflater.inflate(R.layout.item_layout, parent, false)); } default: return null; } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { ((NormalItemVH)holder).render(position + ""); } @Override public int getItemCount() { return NORMAL_ITEM_SIZE; } @Override public int getItemViewType(int position) { return TYPE_NORMAL; } public static class NormalItemVH extends RecyclerView.ViewHolder { public TextView mTextView; public NormalItemVH(View itemView) { super(itemView); mTextView = (TextView) itemView.findViewById(R.id.textView); } public void render(String text) { mTextView.setText("normal-" + text); } }}
附加测试用的MainActivity(xml布局代码省略)
public class MainActivity extends AppCompatActivity { private MyRecyclerView mRecyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getSupportActionBar().hide(); setContentView(R.layout.activity_main); mRecyclerView = (MyRecyclerView) this.findViewById(R.id.recyclerView); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mRecyclerView.setAdapter(new RVAdapter(this)); test(); } private void test() { for (int i = 0; i < 3; i ++) { final View header = LayoutInflater.from(this).inflate(R.layout.extra_item_layout, new FrameLayout(this), false); ((TextView)header.findViewById(R.id.textView)).setText("header-" + i); header.findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mRecyclerView.removeHeader(header); } }); mRecyclerView.addHeader(header); } for (int i = 0; i < 3; i ++) { final View footer = LayoutInflater.from(this).inflate(R.layout.extra_item_layout, new FrameLayout(this), false); ((TextView)footer.findViewById(R.id.textView)).setText("footer-" + i); footer.findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mRecyclerView.removeFooter(footer); } }); mRecyclerView.addFooter(footer); } }}
下面是运行效果图
点击remove按钮会删除header或者footer
0 0
- 一个精简的实现RecyclerView可添加header和footer的Demo
- RecyclerView添加Header和Footer的基本原理
- RecyclerView添加Header和Footer的方法
- RecyclerView优雅的添加Header和Footer
- 封装RecyclerView Adapter 实现可添加多个header和footer,可设置loadingView,低耦合的多种布局。
- 一个能一句话添加header和Footer,并且能滑动删除和交换Item的RecyclerView
- RecyclerView的使用(3)之添加Header和Footer
- RecyclerView的使用(3)之添加Header和Footer
- 使用RecyclerView添加Header和Footer的方法
- 使用RecyclerView添加Header和Footer的方法
- RecyclerView添加Header和Footer
- RecyclerView添加Header和Footer
- RecyclerView添加Header和Footer
- RecyclerView添加header和footer
- RecyclerView添加header和footer
- RecyclerView 添加 Header 和 Footer
- RecyclerView添加Header和Footer
- 使用RecyclerView实现带Header和Footer的GridView
- linux缓冲区解析
- Linux驱动开发环境配置(内核源码树构造)
- 细说JVM系列:虚拟机类加载机制
- 生产者消费者问题
- Boost::filesystem 使用小笔记
- 一个精简的实现RecyclerView可添加header和footer的Demo
- 让bochs调试时的终端输出有颜色的文本的方法
- Android事件分发机制
- 给即将大三的自己一封信
- 缓存基础- 缓存包含哪些
- POJ 2286 The Rotation Game(IDA*)
- NYOJ 914 Yougth的最大化
- C++11学习笔记(2)
- python构建网站的几个第三方库