美文网首页Android 进阶技术篇专题我爱编程Android开发
Android 万能的强大的RecyclerView适配器Ada

Android 万能的强大的RecyclerView适配器Ada

作者: SwitchLife | 来源:发表于2019-01-05 23:50 被阅读1次

    开篇

      相信大家在项目的开发中都用到了QuickAdapter,也感觉到了它确实提升了一些我们的开发效率。不仅仅你用了,我也用了,但是我还是觉得它还有很大的提升空间。为此,我特意抽时间封装了此RecyclerView适配器。

    效果截屏

    PullToRefreshRecyclerView

    立即体验

    扫描以下二维码下载体验App(体验App内嵌版本更新检测功能):


    扫描下载体验App

    传送门:https://github.com/JustinRoom/SimpleAdapterDemo

    gradle引用

        implementation 'jsc.kit.adapter:adapter-component:_latestVersion'
    

    简析源码

    public abstract class BaseHeaderFooterAdapter<H, D, F, E, VH extends BaseHeaderFooterAdapter.BaseViewHolder> extends RecyclerView.Adapter<VH> {}

    1、封装了4中ViewType类型:H——头(header)、D——数据(data)、F——尾(footer)、E——空列表(empty)

        /**
         * header 视图
         */
        public static final int TYPE_HEADER = 1000;
        /**
         * data 数据视图
         */
        public static final int TYPE_DATA = 1001;
        /**
         * footer 视图
         */
        public static final int TYPE_FOOTER = 1002;
        /**
         * 空列表视图
         */
        public static final int TYPE_EMPTY = 1003;
    
        private List<H> headers = new ArrayList<>();
        private List<D> data = new ArrayList<>();
        private List<F> footers = new ArrayList<>();
        private List<E> empties = new ArrayList<>();
    

    2、获取position位置的ViewType

        @Override
        public int getItemCount() {
            return getHeaderSize() + getInternalSize() + getFooterSize();
        }
    
        @ViewType
        @Override
        public int getItemViewType(int position) {
            if (position >= getHeaderSize() + getInternalSize() + getFooterSize())
                return UNKNOWN;
            if (position >= getHeaderSize() + getInternalSize())
                return TYPE_FOOTER;
            if (position >= getHeaderSize())
                return isEmptyData() ? TYPE_EMPTY : TYPE_DATA;
            if (position >= 0)
                return TYPE_HEADER;
            return UNKNOWN;
        }
    
        private int getInternalSize() {
            return isEmptyData() ? getEmptySize() : getDataSize();
        }
    

    3、封装BaseViewHolder,添加一些常用方法。
    public static class BaseViewHolder extends RecyclerView.ViewHolder {}

    常用方法:
    public <V extends View> V findViewById(@IdRes int id)
    public void setText(@IdRes int id, CharSequence txt)
    public void setTextColor(@IdRes int id, @ColorInt int color)
    public void setTextSize(@IdRes int id, float size)
    public void setTextSize(@IdRes int id, int unit, float size)
    public void setVisibility(@IdRes int id, int visibility)
    public void setSelected(@IdRes int id, boolean selected)
    public void setEnabled(@IdRes int id, boolean enable)
    public void setBackgroundColor(@IdRes int id, @ColorInt int color)
    public void setBackgroundResource(@IdRes int id, @DrawableRes int resId)
    public void setBackground(@IdRes int id, Drawable background)
    public void setTag(@IdRes int id, final Object tag)
    public void setTag(@IdRes int id, int key, final Object tag)
    void setPositionTag(int position)
    void addOnItemClickListener(View.OnClickListener listener)
    void addOnItemLongClickListener(View.OnLongClickListener listener)
    void addOnChildClickListener(@IdRes int id, View.OnClickListener listener)
    void addOnChildLongClickListener(@IdRes int id, View.OnLongClickListener listener)

    4、绑定View

        @CallSuper
        @Override
        public void onBindViewHolder(@NonNull VH holder, int position) {
            holder.setPositionTag(position);
            holder.addOnItemClickListener(onItemClickListener == null ? null : getDefaultItemClickListener());
            holder.addOnItemLongClickListener(onItemLongClickListener == null ? null : getDefaultItemLongClickListener());
            switch (getItemViewType(position)) {
                case TYPE_HEADER:
                    onBindHeaderViewHolder(holder, position, getHeaderAt(position));
                    break;
                case TYPE_DATA:
                    onBindDataViewHolder(holder, position, getDataAt(position));
                    break;
                case TYPE_FOOTER:
                    onBindFooterViewHolder(holder, position, getFooterAt(position));
                    break;
                case TYPE_EMPTY:
                    onBindEmptyViewHolder(holder, position, getEmptyAt(position));
                    break;
                case UNKNOWN:
                    break;
            }
        }
    

    5、根据不同的ViewType创建不同View视图:SimpleAdapter

    public class SimpleAdapter<H, D, F, E> extends BaseHeaderFooterAdapter<H, D, F, E, BaseHeaderFooterAdapter.BaseViewHolder> {
    
        public SimpleAdapter() {
        }
    
        public SimpleAdapter(@LayoutRes int dataLayoutId) {
            super(dataLayoutId);
        }
    
        @NonNull
        @Override
        public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
            switch (viewType) {
                case TYPE_HEADER:
                    if (getHeaderLayoutId() == -1)
                        throw new IllegalArgumentException(getClass().getSimpleName() + " : please set header layout first.");
                    return new BaseViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(getHeaderLayoutId(), viewGroup, false));
                case TYPE_DATA:
                    if (getDataLayoutId() == -1)
                        throw new IllegalArgumentException(getClass().getSimpleName() + " : please set footer layout first.");
                    return new BaseViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(getDataLayoutId(), viewGroup, false));
                case TYPE_FOOTER:
                    if (getFooterLayoutId() == -1)
                        throw new IllegalArgumentException(getClass().getSimpleName() + " : please set footer layout first.");
                    return new BaseViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(getFooterLayoutId(), viewGroup, false));
                case TYPE_EMPTY:
                    return new BaseViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(getEmptyLayoutId() == -1 ? R.layout.recycler_default_empty_list_layout : getEmptyLayoutId(), viewGroup, false));
                default:
                    TextView textView = new TextView(viewGroup.getContext());
                    textView.setTextColor(Color.RED);
                    textView.setGravity(Gravity.CENTER);
                    textView.setText("Unknown view type");
                    textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                    return new BaseViewHolder(textView);
            }
        }
    }
    

    使用示例

    • 1、简单使用示例:
            RecyclerView recyclerView;
    
            adapter2 = new SimpleAdapter2<MaterielOrderDetail, MaterielDetail, Object>() {
                @Override
                protected void onBindHeaderViewHolder(@NonNull BaseViewHolder holder, int position, MaterielOrderDetail headerBean) {
                    holder.setText(R.id.tv_company_name, formatValue("公司名称:", headerBean.getOrgName()));
                    holder.setText(R.id.tv_type, formatValue("\u3000类型:", headerBean.getEventTypeName()));
                    holder.setText(R.id.tv_warehouse_name, formatValue("仓库名称:", headerBean.getWarehouseName()));
                    holder.setText(R.id.tv_partner_name, formatValue("供应商:", headerBean.getPartnerName()));
                    if (headerBean.getCreateTime() > 0) {
                        holder.setText(R.id.tv_create_time, formatValue("创建时间:", format.format(new Date(headerBean.getCreateTime()))));
                    } else {
                        holder.setText(R.id.tv_create_time, "");
                    }
                    holder.setText(R.id.tv_creator, formatValue("创建人:", headerBean.getCreatePersonName()));
                    //已经审核通过
                    if (MaterielMenu.orderStatus.get(2).getKey().equals(headerBean.getStatus())) {
                        holder.setText(R.id.tv_auditing_time, formatValue("审核时间:", format.format(new Date(headerBean.getApproveTime()))));
                        holder.setText(R.id.tv_auditor, formatValue("审核人:", headerBean.getApprovePersonName()));
                    } else {
                        holder.setText(R.id.tv_auditing_time, formatValue("审核时间:", "--"));
                        holder.setText(R.id.tv_auditor, formatValue("审核人:", "--"));
                    }
    
                    holder.setText(R.id.tv_storage_type_label, String.format(Locale.CHINA, "%s物料:", opAction1 == IMateriel.OP_ACTION_IN ? "入库" : "出库"));
                }
    
                @Override
                protected void onBindDataViewHolder(@NonNull BaseViewHolder holder, int position, MaterielDetail dataBean) {
                    holder.setText(R.id.tv_materiel_name, dataBean.getMaterialName());
                    if (dataBean.getBatchManage()) {
                        holder.setText(R.id.tv_materiel_batch, String.format(Locale.CHINA, "(%s)", dataBean.getBatch()));
                    } else {
                        holder.setText(R.id.tv_materiel_batch, "");
                    }
                    holder.setVisibility(R.id.btn_materiel_delete, View.GONE);
                    holder.setText(R.id.tv_business_unit, formatValue("业务单位:", dataBean.getMultiUnitName()));
                    holder.setText(R.id.tv_business_number, formatValue("业务数量:", String.valueOf(dataBean.getQuantity())));
                    holder.setText(R.id.tv_accounting_unit, formatValue("核算单位:", dataBean.getAccountUnitName()));
                    holder.setText(R.id.tv_accounting_number, formatValue("核算数量:", String.valueOf(dataBean.getAccountQuantity())));
                }
    
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd\u2000HH:mm", Locale.CHINA);
    
                CharSequence formatValue(String label, String value) {
                    if (value == null || value.trim().length() == 0) {
                        return label;
                    }
                    SpannableString spannableString = new SpannableString(label + value);
                    spannableString.setSpan(new ForegroundColorSpan(0xFF90FFBE), label.length(), label.length() + value.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    return spannableString;
                }
            };
            adapter2.setHeaderLayoutId(R.layout.breed_fragment_materiel_detail_header);
            adapter2.setDataLayoutId(R.layout.breed_list_item_materiel);
            adapter2.bindRecyclerView(recyclerView);
            adapter2.addHeader(new MaterielOrderDetail());
    
    • 2、各种事件监听:

    2.1、itemView的点击事件监听:

    public interface OnItemClickListener<H, D, F, E> {
        //每一条header的点击监听
        void onHeaderItemClick(@NonNull View headerItemView, int position, H headerBean);
        //每一条data的点击监听
        void onDataItemClick(@NonNull View dataItemView, int position, D dataBean);
        //每一条footer的点击监听
        void onFooterItemClick(@NonNull View footerItemView, int position, F footerBean);
        //每一条empty的点击监听
        void onEmptyItemClick(@NonNull View emptyItemView, int position, E emptyBean);
    }
    

    2.2、itemViewchild view的点击事件监听

    public interface OnItemChildClickListener<H, D, F, E> {
        //header child view点击监听
        void onHeaderItemChildClick(@NonNull View headerChild, int position, H headerBean);
        //data child view点击监听
        void onDataItemChildClick(@NonNull View dataItemChild, int position, D dataBean);
        //footer child view点击监听
        void onFooterItemChildClick(@NonNull View footerChild, int position, F footerBean);
        //empty child view点击监听
        void onEmptyItemChildClick(@NonNull View emptyChild, int position, E emptyBean);
    }
    

    2.3、itemView的长按事件监听:

    public interface OnItemLongClickListener<H, D, F, E> {
        //每一条header的长按监听
        boolean onHeaderItemLongClick(@NonNull View headerItemView, int position, H headerBean);
        //每一条data的长按监听
        boolean onDataItemLongClick(@NonNull View dataItemView, int position, D dataBean);
        //每一条footer的长按监听
        boolean onFooterItemLongClick(@NonNull View footerItemView, int position, F footerBean);
        //每一条empty的长按监听
        boolean onEmptyItemLongClick(@NonNull View emptyItemView, int position, E emptyBean);
    }
    

    2.4、itemViewchild view的长按事件监听

    public interface OnItemChildLongClickListener<H, D, F, E> {
        //header child view长按监听
        boolean onHeaderItemChildLongClick(@NonNull View headerChild, int position, H headerBean);
        //data child view长按监听
        boolean onDataItemChildLongClick(@NonNull View dataItemChild, int position, D dataBean);
        //footer child view长按监听
        boolean onFooterItemChildLongClick(@NonNull View footerChild, int position, F footerBean);
        //empty child view长按监听
        boolean onEmptyItemChildLongClick(@NonNull View emptyChild, int position, E emptyBean);
    }
    
    

    使用介绍就到这里。
    如果你觉得还不错的话,在GitHub上给一颗星星✨支持下吧。谢谢!如果在使用过程中不懂(或需要改进的地方),可以在评论里给我留言,也可以联系我。
    微信:eoy9527QQ:1006368252

    篇尾

    一个人最怕不老实,青年人最可贵的是老实作风。"老实"就是不自欺欺人,做到不欺骗人家容易,不欺骗自己最难。"老实作风"就是脚踏实地,不占便宜。世界上没有便宜的事,谁想占便宜水就会吃亏。 —— 徐特立

    相关文章

      网友评论

        本文标题:Android 万能的强大的RecyclerView适配器Ada

        本文链接:https://www.haomeiwen.com/subject/uwodrqtx.html