RecyclerView封装——添加Header、Footer(在网格瀑布流布局中独占一行)

转载请标明出处:
http://blog.csdn.net/sinat_15877283/article/details/50913998;
本文出自: 【温利东的博客】

前言 FOREWORD

  • 很多人(包括我)已经开始抛弃ListView和GridView转为RecyclerView了。
    网络上有很多关于RecyclerView加头加尾的文章,其中组合模式占多,这种模式大概思路是自定义一个customView 然后在里面放置 一个头布局容器、一个尾布局容器,一个RecyclerView容器 :
    RecyclerView封装——添加Header、Footer(在网格瀑布流布局中独占一行)_第1张图片

这种写法太low了…..原本recyclerView层级就很深了,这相当于在加深了一层,碰上稍微复杂一些的item,手机不是要卡到爆吗?这让低端机怎么活!!!

  • 最近在看《App研发录》这本书籍,感觉之前对recyclerView封装的不到位,借此完善一下。

正文 BODY

说说本篇文章需要解决的问题,了解需求我们才能有针对性的进行封装:

  • 可为RecyclerView 添加/移除 多个Header和Footer
  • 解决HeaderView、FooterView在网格/瀑布流中 布局不足一行问题
  • 可拓展、低耦合

行为封装: IAdapter< VH, M>:

/** * Created by wenld- on 2016/3/17. */
public interface IAdapter<VH, M> {
    /** 设置 主内容 View类型 */
    int getAdvanceViewType(int position);

    /** 加头View */
    void addHeaderView(View headerView);

    /** 加尾View */
    void addFooterView(View footerView);

    /** 数据绑定View */
    void onBindAdvanceViewHolder(VH holder, int i);

    /** 加载 ViewGroup 容器 */
    RecyclerView.ViewHolder onCreateAdvanceViewHolder(ViewGroup parent, int viewType);
}

需要事先了解的技术点

  public int getItemViewType(int position) {...}
    @Override
  public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager instanceof GridLayoutManager) {
            final GridLayoutManager gridManager = ((GridLayoutManager) manager);
            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    return (getItemViewType(position) % HeaderFooterFlag == 0)
                            ? gridManager.getSpanCount() : 1;
                }
            });
        }
    }

    @Override
    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
        if (lp != null
                && lp instanceof StaggeredGridLayoutManager.LayoutParams
                && holder.getLayoutPosition() == 0) {
            StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
            p.setFullSpan(true);
        }
    }
  • 判断View类型: public int getItemViewType(int position)
  • 让头尾View在 GridLayoutManager,StaggeredGridLayoutManager布局中 占用1行

封装篇 AdvancedAdapter:

/** * Created by wenld- on 2015/9/24. * <p/> * 简单封装 加头加尾 recyclerView 适配器 * 在布局 GridLayoutManager,StaggeredGridLayoutManager 头尾占一行 */
public abstract class AdvancedAdapter<VH extends AdvancedAdapter.ViewHolder, M> extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements IAdapter<VH, M> {
    private ArrayList<View> mHeaderViews = new ArrayList<>();
    private ArrayList<View> mFooterViews = new ArrayList<>();
    protected ItemClickInterface<M> listener;
    protected List<M> mData;

    public final void addHeaderView(View headerView) {
        mHeaderViews.add(headerView);
    }
    public final void addFooterView(View footerView) {
        mFooterViews.add(footerView);
    }

    private SparseIntArray mHeaderViewTypes = new SparseIntArray();
    private SparseIntArray mFooterViewTypes = new SparseIntArray();
    private final static int HeaderFooterFlag = 100000;

    @Override
        public int getItemViewType(int position) {
        if (mHeaderViews.size() > 0 && position < mHeaderViews.size()) {
            //用position作为HeaderView 的 ViewType标记
            //记录每个ViewType标记
            position = (position + 1) * HeaderFooterFlag;
            mHeaderViewTypes.put(position, position);
            return position;
        }

        if (mFooterViews.size() > 0 && position > getAdvanceCount() - 1 + mHeaderViews.size()) {
            //用position作为FooterView 的 ViewType标记
            position = (position + 1) * HeaderFooterFlag;
            mHeaderViewTypes.put(position, position);
            return position;
        }

        return getAdvanceViewType(position);
    }

    /** * @return */
    public int getAdvanceCount() {
        int a = 0;
        if (mData != null) {
            a = mData.size();
        }
        return a;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (mHeaderViewTypes.get(viewType, -1) != (-1)) {
            return new HeaderHolder(mHeaderViews.get(viewType / 100000 - 1));
        }

        if (mFooterViewTypes.get(viewType, -1) != (-1)) {
            int index = viewType / 100000 - 1 - getAdvanceCount() - mHeaderViews.size();
            return new FooterHolder(mFooterViews.get(index));
        }

        return onCreateAdvanceViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        if (mFooterViews.size() > 0 && (position > getAdvanceCount() - 1 + mHeaderViews.size())) {
            return;
        }

        if (mHeaderViews.size() > 0) {
            if (position < mHeaderViews.size()) {
                return;
            }
            onBindAdvanceViewHolder((VH) holder, position - mHeaderViews.size());
            return;
        }
        onBindAdvanceViewHolder((VH) holder, position - mHeaderViews.size());
    }

    class HeaderHolder extends RecyclerView.ViewHolder {
        public HeaderHolder(View itemView) {
            super(itemView);
        }
    }

    class FooterHolder extends RecyclerView.ViewHolder {
        public FooterHolder(View itemView) {
            super(itemView);
        }
    }

    public abstract class ViewHolder extends RecyclerView.ViewHolder implements IViewHolder {
        public ViewHolder(View itemView) {
            super(itemView);
        }
        public int getAdpPosition() {
            return Selected(getAdapterPosition());
        }
    }

    public M getItem(int position) {
        if (getItemCount() == 0) {
            return null;
        }
        return mData.get(position);
    }

    @Override
    public int getItemCount() {
        if (mHeaderViews.size() > 0 && mFooterViews.size() > 0) {
            return getAdvanceCount() + mHeaderViews.size() + mFooterViews.size();
        }
        if (mHeaderViews.size() > 0) {
            return getAdvanceCount() + mHeaderViews.size();
        }
        if (mFooterViews.size() > 0) {
            return getAdvanceCount() + mFooterViews.size();
        }

        return getAdvanceCount();
    }

    public int Selected(int position) {
        if (mHeaderViews.size() > 0 && position < mHeaderViews.size()) {
            return -1;
        }
        if (mFooterViews.size() > 0 && position > getAdvanceCount() - 1 + mHeaderViews.size()) {
            return -1;
        } else {
            return position - mHeaderViews.size();
        }
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);

        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager instanceof GridLayoutManager) {
            final GridLayoutManager gridManager = ((GridLayoutManager) manager);
            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    return (getItemViewType(position) % HeaderFooterFlag == 0)
                            ? gridManager.getSpanCount() : 1;
                }
            });
        }
    }

    @Override
    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
        if (lp != null
                && lp instanceof StaggeredGridLayoutManager.LayoutParams
                && holder.getLayoutPosition() == 0) {
            StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
            p.setFullSpan(true);
        }
    }

    @Override
    public void setData(List<M> mDataList) {
        this.mData = mDataList;
    }

    @Override
    public List<M> getData() {
        return mData;
    }

    @Override
    public void setListener(ItemClickInterface<M> listener) {
        this.listener = listener;
    }
}

使用篇:MyAdapter:

/** * Created by wenld- on 2016/3/17. */
public class MyAdapter extends AdvancedAdapter<ImageListAdapter.ViewHolder, ImagesListEntity> {
    private Context mContext;

    @Override
    public int getAdvanceViewType(int position) {
        return position;
    }

    @Override
    public void onBindAdvanceViewHolder(ViewHolder holder, int i) {
      .....
    }

    @Override
    public RecyclerView.ViewHolder onCreateAdvanceViewHolder(ViewGroup parent, int viewType) {
        ViewHolder vh = .....
        return vh;
    }

    public MyAdapter (Context mContext, List<ImagesListEntity> mData, ItemClickInterface listener) {
        ...
    }

    public class ViewHolder extends AdvancedAdapter.ViewHolder {
        public ImageView icon;

        public ViewHolder(View v) {
            super(v);
            v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (listener != null) {
                        listener.onItemClick(mData.get(getAdpPosition()), getAdpPosition());
                    }
                }
            });
            icon = (ImageView) v.findViewById(R.id.list_item_images_list_image);
        }
    }
}

结论

样式做的不好看,但这不是重点…..(哈哈哈哈,随手加了一个TextView)

对于控件类的封装最好不要用组合模式!!!
对于控件类的封装最好不要用组合模式!!!
对于控件类的封装最好不要用组合模式!!!
重要的事情说三遍………
demo 戳这里、戳!戳!戳!

希望我的分享能对你有帮助,也希望你能提出你的意见和想法,一起分享,共同成长。
转载请标明出处: http://blog.csdn.net/sinat_15877283/article/details/50913998;

你可能感兴趣的:(android,header,适配器,Material设计,加头加尾)