一个精简的实现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
原创粉丝点击