RecyclerView.Adapter的封装类

我们知道,Recyclerview是不直接支持点击事件以及添加头部view和底部view的,所以我们有必要进行进一步的封装。

public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerViewHolder> {
    private static final int TYPE_ITEM = 0;
    private static final int TYPE_HEADER = -1;
    private static final int TYPE_FOOTER = 1;
    protected final List<T> mItems;
    protected final Context mContext;
    protected LayoutInflater mInflater;
    private OnItemClickListener mClickListener;
    private OnItemLongClickListener mLongClickListener;

    public BaseRecyclerAdapter(Context ctx, List<T> list) {
        mItems = (list != null) ? list : new ArrayList<T>();
        mContext = ctx;
        mInflater = LayoutInflater.from(ctx);
        if (isHeaderExist()) mItems.add(0, null);
        if (isFooterExist()) mItems.add(mItems.size(), null);
    }

    public void setList(List<T> list) {
        mItems.clear();
        mItems.addAll(list);
        notifyDataSetChanged();
    }

    /**
     * 如果你要用在GridLayout中使用header或footer,记得在setLayoutManager之后调用该方法
     *
     * @param manager
     */
    public void getGridLayoutManager(@NonNull final GridLayoutManager manager) {
        manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                return (position == getFooterPosition() || position == getHeaderPosition()) ?
                        manager.getSpanCount() : 1;
            }
        });
    }

    /**
     * 如果需要在子类重写该方法,建议参照此形式
     *
     * @param position
     * @return
     */
    @Override
    public int getItemViewType(int position) {
        if (!isHeaderExist() && !isFooterExist())
            return super.getItemViewType(position);
        else {
            if (position == getHeaderPosition())
                return TYPE_HEADER;
            if (position == getFooterPosition())
                return TYPE_FOOTER;
            return TYPE_ITEM;
        }
    }

    public int selectedPosition = -5;

    @Override
    public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        int layoutId = -1;
        switch (viewType) {
            case TYPE_HEADER:
                layoutId = getHeaderLayoutId();
                break;
            case TYPE_FOOTER:
                layoutId = getFooterLayoutId();
                break;
            case TYPE_ITEM:
                layoutId = getItemLayoutId(viewType);
                break;
            default:
                throw new RuntimeException("illegal viewType!");
        }
        if (layoutId == -1)
            throw new RuntimeException("The method getHeaderLayoutId() return the wrong id, you should override it and return the correct id");

        final RecyclerViewHolder holder = new RecyclerViewHolder(mContext,
                mInflater.inflate(layoutId, parent, false));
        if (mClickListener != null && viewType != TYPE_HEADER && viewType != TYPE_FOOTER) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (!isHeaderExist()) {
                        mClickListener.onItemClick(holder.itemView, holder.getLayoutPosition());
                    }
                    else{
                        mClickListener.onItemClick(holder.itemView, holder.getLayoutPosition() - 1);
                    }
                }
            });
        }
        if (mLongClickListener != null && viewType != TYPE_HEADER && viewType != TYPE_FOOTER) {
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    if (!isHeaderExist()) {
                        mLongClickListener.onItemLongClick(holder.itemView, holder.getLayoutPosition());

                    } else {
                        mLongClickListener.onItemLongClick(holder.itemView, holder.getLayoutPosition() - 1);
                    }
                    return true;
                }
            });
        }
        return holder;
    }

    protected int getFooterLayoutId() {
        return -1;
    }

    final public boolean isFooterExist() {
        return getFooterLayoutId() != -1;
    }

    protected int getHeaderLayoutId() {
        return -1;
    }

    final public boolean isHeaderExist() {
        return getHeaderLayoutId() != -1;
    }

    final public int getHeaderPosition() {
        if (isHeaderExist()) return 0;
        return -1;
    }

    final public int getFooterPosition() {
        if (isFooterExist()) return getItemCount() - 1;
        return -2;
    }

    @Override
    public void onBindViewHolder(RecyclerViewHolder holder, int position) {
        if (position == getFooterPosition()) bindFooter(holder, position);
        else if (position == getHeaderPosition()) bindHeader(holder, position);
        else bindData(holder, position, mItems.get(position));
    }

    @Override
    public int getItemCount() {
        return mItems.size();
    }

    /**
     * 添加数据到特定的位置,该位置已考虑header和footer
     *
     * @param pos
     * @param item
     */
    public void add(int pos, T item) {
        if (pos != getHeaderPosition() && pos != getFooterPosition() + 1) {
            mItems.add(pos, item);
            notifyItemInserted(pos);
        } else {
            try {
                throw new Exception("your position to add or delete should consider the header and footer.");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 在特定位置删除数据,该位置已考虑header和footer
     *
     * @param pos
     */
    public void delete(int pos) {
        if (pos != getHeaderPosition() && pos != getFooterPosition()) {
            mItems.remove(pos);
            notifyItemRemoved(pos);
        } else {
            try {
                throw new Exception("your position to add or delete should consider the header and footer.");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 在特定的位置之间交换位置,该位置已考虑header和footer
     *
     * @param fromPosition
     * @param toPosition
     */
    public void swap(int fromPosition, int toPosition) {
        int head = getHeaderPosition();
        int foot = getFooterPosition();
        if (fromPosition != head && toPosition != head && fromPosition != foot && toPosition != foot) {
            Collections.swap(mItems, fromPosition, toPosition);
            notifyItemMoved(fromPosition, toPosition);
        } else {
            try {
                throw new Exception("your position to swap should consider the header and footer.");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    final public void setOnItemClickListener(OnItemClickListener listener) {
        mClickListener = listener;
    }

    final public void setOnItemLongClickListener(OnItemLongClickListener listener) {
        mLongClickListener = listener;
    }

    /**
     * 重写该方法进行header视图的数据绑定
     *
     * @param holder
     * @param position
     */
    protected void bindHeader(RecyclerViewHolder holder, int position) {
    }

    /**
     * 重写该方法进行footer视图的数据绑定
     *
     * @param holder
     * @param position
     */
    protected void bindFooter(RecyclerViewHolder holder, int position) {
    }

    /**
     * 重写该方法,根据viewType设置item的layout
     *
     * @param viewType 通过重写getItemViewType()设置,默认item是0
     * @return
     */
    abstract protected int getItemLayoutId(int viewType);

    /**
     * 重写该方法进行item数据项视图的数据绑定
     *
     * @param holder   通过holder获得item中的子View,进行数据绑定
     * @param position 该item的position
     * @param item     映射到该item的数据
     */
    abstract protected void bindData(RecyclerViewHolder holder, int position, T item);

    public interface OnItemClickListener {
        void onItemClick(View itemView, int pos);
    }

    public interface OnItemLongClickListener {
        void onItemLongClick(View itemView, int pos);
    }

}
RecyclerViewHolder:
public class RecyclerViewHolder extends RecyclerView.ViewHolder {
    private SparseArray<View> mViews;//集合类,layout里包含的View,以view的id作为key,value是view对象
    private Context mContext;//上下文对象

    public RecyclerViewHolder(Context ctx, View itemView) {
        super(itemView);
        mContext = ctx;
        mViews = new SparseArray<>();
    }


    public View getItemView() {
        return itemView;
    }

    private <T extends View> T findViewById(int viewId) {
        View view = mViews.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            mViews.put(viewId, view);
        }
        return (T) view;
    }

    public View getView(int viewId) {
        return findViewById(viewId);
    }

    public TextView getTextView(int viewId) {
        return (TextView) getView(viewId);
    }
    public TextView getTextView(int viewId, View view) {
        return (TextView) view.findViewById(viewId);
    }
    public Button getButton(int viewId) {
        return (Button) getView(viewId);
    }

    public ImageView getImageView(int viewId) {
        return (ImageView) getView(viewId);
    }

    public ImageView getImageView(View view, int viewId) {
        return (ImageView) view.findViewById(viewId);
    }

    public ImageButton getImageButton(int viewId) {
        return (ImageButton) getView(viewId);
    }

    public EditText getEditText(int viewId) {
        return (EditText) getView(viewId);
    }

    public RecyclerViewHolder setText(int viewId, String value) {
        TextView view = findViewById(viewId);
        view.setText(value);
        return this;
    }

    public RecyclerViewHolder setBackground(int viewId, int resId) {
        View view = findViewById(viewId);
        view.setBackgroundResource(resId);
        return this;
    }

    public RecyclerViewHolder setClickListener(int viewId, View.OnClickListener listener) {
        View view = findViewById(viewId);
        view.setOnClickListener(listener);
        return this;
    }


}

使用:具体adapter类继承BaseRecyclerAdapter<T>即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AD钙奶-lalala

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值