Android 万能适配器BaseQuickAdapter操作及免费源码

4,477 阅读8分钟

Android 万能适配器BaseQuickAdapter操作及免费源码,本篇巨长无比,非常详细的介绍了BaseQuickAdapter,若有帮助到您,记得点个赞哦~

再大的伤痛,睡一觉就把它忘了,背着昨天追赶明天,会累坏了每一个当下。烦恼不过夜,健忘才幸福。真正能让你倒下的,不是对手,而是自己内心的绝望。时间可以愈合一颗破碎的心,也许只有夜晚一床温暖的棉被和一个好梦,才可以慰藉每天有太多不如意的我们。

简介

  • BaseQuickAdapter是为了配合RecyclerView使用的适配器
  • 可以添加头部、尾部,下拉刷新、上拉加载, 没有更多数据提示等
  • 可以实现下滑动画(5种,可自定义)
  • 可以拖拽移动位置,可以右滑删除
  • 可实现单布局,多布局,多级列表使用
  • 可实现数据未显示时的空布局等等

反正就是好用的不得了~

导入依赖

步骤图(1.1):
在这里插入图片描述

 maven { url "https://jitpack.io" }

步骤图(1.2):
在这里插入图片描述
添加依赖:

//BasequickAdapter
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'

我现在的studio是4.1的,所以不需要添加RecyclerView依赖

简单使用

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".OrdinaryActivity">
    <Button
        android:id="@+id/button"
        android:text="加载数据"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <androidx.recyclerview.widget.RecyclerView
        android:layout_below="@+id/button"
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

代码图(2.1):
在这里插入图片描述
最简单使用:继承自BaseQuickAdapter:

public class RecyclerViewAdapter extends BaseQuickAdapter<ItemBean, BaseViewHolder> {

  public RecyclerViewAdapter(int layoutResId, @Nullable List<ItemBean> data){
        super(layoutResId, data);
    }
    @Override
    protected void convert(BaseViewHolder helper, ItemBean item) {
        helper.setText(R.id.tv, item.getIndex());
    }
}

辅助Bean类:

public class ItemBean {
    String index;
    public ItemBean(String index) {
        this.index = index;
    }
    public String getIndex() {
        return index;
    }
}

完整测试代码:

public RecyclerViewAdapter adapter;

 ArrayList<ItemBean> itemBeans = new ArrayList<>();
 
recycler.setLayoutManager(new LinearLayoutManager(this));

for (int i = 0; i < 50; i++) {
     itemBeans.add(new ItemBean("学员 " + i));
}

//创建适配器 并绑定适配器
recycler.setAdapter(adapter = new RecyclerViewAdapter(R.layout.item_layout, itemBeans));

适配器(RecyclerViewAdapter)参数:

  • 参数一:item布局
  • 数据

效果图(3.1):

添加头尾布局

View headView = LayoutInflater.from(this).inflate(R.layout.item_head_layout, null);
  
View foodView = LayoutInflater.from(this).inflate(R.layout.item_foot_layout, null);
//头布局
adapter.addHeaderView(headView);
//尾布局
adapter.addFooterView(foodView);

效果图(3.2):

添加空布局

请求数据时显示

当点击按钮时加载数据:

//加载数据点击事件 
 button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //初始化数据
                initItem();
                adapter.notifyDataSetChanged();
            }
        });


View view = LayoutInflater.from(this).inflate(R.layout.no_layout, null);
 //空布局 没有数据时显示
adapter.setEmptyView(view);

效果图(3.3):

点击事件

 //单击事件
        adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                Toast.makeText(OrdinaryActivity.this, "单击了 :" + position, Toast.LENGTH_SHORT).show();
            }
        });

        //长按事件
        adapter.setOnItemLongClickListener(new BaseQuickAdapter.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(BaseQuickAdapter adapter, View view, int position) {
                Toast.makeText(OrdinaryActivity.this, "长按了 :" + position, Toast.LENGTH_SHORT).show();
                return false;
            }
        });

效果图(3.4):

滑动动画

 //渐变动画
        adapter.openLoadAnimation(BaseQuickAdapter.ALPHAIN);
        //从右到左动画
//        adapter.openLoadAnimation(BaseQuickAdapter.SCALEIN);
        //从下到上动画
//        adapter.openLoadAnimation(BaseQuickAdapter.SLIDEIN_BOTTOM);
        //从左到右动画
//        adapter.openLoadAnimation(BaseQuickAdapter.SLIDEIN_LEFT);
        //从右到左动画
//        adapter.openLoadAnimation(BaseQuickAdapter.SLIDEIN_RIGHT);

//动画是否重复播放 false重复播放 默认为true不重复模仿
adapter.isFirstOnly(false);
ALPHAINSCALEINSLIDEIN_BOTTOM
效果图(3.5):效果图(3.6):效果图(3.7):
SLIDEIN_LEFTSLIDEIN_RIGHT
效果图(3.8):效果图(3.9):

自定义动画

  //自定义动画
       adapter.openLoadAnimation(new BaseAnimation() {
            @Override
            public Animator[] getAnimators(View view) {
                return new Animator[]{
        /*               
         * scaleX / scaleY 缩放动画
         *  alpha   透明度动画   取值 1-0
         *  rotationX /rotationY 旋转动画   取值 0-360
         *  translationX / translationY 移动动画
         *      translationX正数向右移动,负数向左移动
         *      translationY正数向下移动,负数向上移动
         **/

          //scaleX / scaleY 缩放动画
//         ObjectAnimator.ofFloat(view, "scaleX", 1, 2.5f, 1),
//         ObjectAnimator.ofFloat(view, "scaleY", 1, 2.5f, 1),

//         alpha   透明度动画   取值 1-0
//         ObjectAnimator.ofFloat(view, "alpha", 1, 0.2f, 1),

//          rotationX /rotationY 旋转动画   取值 0-360
//          ObjectAnimator.ofFloat(view, "rotationX", 0,180,0),
//          ObjectAnimator.ofFloat(view, "rotationY", 0,180,0),

//          translationX / translationY 移动动画
//                -  translationY正数向下移动,负数向上移动
//                 -  translationY正数向下移动,负数向上移动
            ObjectAnimator.ofFloat(view, "translationX", 0,180,0),
            ObjectAnimator.ofFloat(view, "translationY", 0,180,0),
                };
            }
        });
scaleX /scalealpha
效果图(3.10):效果图(3.11):
rotationX /rotationYtranslationX / translationY
效果图(3.12):效果图(3.13):

参数参考文档

上拉加载更多

adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
            @Override
            public void onLoadMoreRequested() {
                //recycler请求1s
                recycler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(OrdinaryActivity.this, "请求 1s 结束", Toast.LENGTH_SHORT).show();

                        //加载完成 没有更多数据
//                        adapter.loadMoreEnd();

                        //重新请求
//                        adapter.loadMoreComplete();

                        //加载失败
                        adapter.loadMoreFail();

                        //下拉加载完成不显示文字
//                        adapter.setEnableLoadMore(false);

                    }

                }, 1000);
            }
 }, recycler);
adapter.loadMoreEnd();adapter.loadMoreComplete();
效果图(3.14):效果图(3.15):
adapter.loadMoreFail();adapter.setEnableLoadMore(false);
效果图(3.16):效果图(3.17):

下拉刷新

//允许下拉
        adapter.setUpFetchEnable(true);

        //下拉监听
        adapter.setUpFetchListener(new BaseQuickAdapter.UpFetchListener() {
            @Override
            public void onUpFetch() {
                Toast.makeText(OrdinaryActivity.this, "下拉", Toast.LENGTH_SHORT).show();
            }
        });

效果图(3.18):

预加载

adapter.setPreLoadNumber(20);

这里没有请求网络数据,效果不明显,就不看了

(底部会给出完整代码)

双布局适配器

public class SectionAdapter extends BaseSectionQuickAdapter<SectionBean,BaseViewHolder> {
     public SectionAdapter(int layoutResId, int sectionHeadResId, List data) {
        super(layoutResId, sectionHeadResId, data);
    }

    /**
     * 布局一
     */
    @Override
    protected void convert(BaseViewHolder helper, SectionBean item) {
         helper.setText(R.id.tv, item.getName());
    }

    /**
     * 布局二
     */
    @Override
    protected void convertHead(BaseViewHolder helper,final SectionBean item) {
        helper.setText(R.id.tv, item.getName());
    }
}

BaseSectionQuickAdapter泛型介绍:

  • 泛型一:需要传递的数据类
  • 泛型二:BaseViewHolder

BaseSectionQuickAdapter参数介绍:

  • layoutResId参数一:布局一
  • sectionHeadResId参数二:布局二
  • data参数三:数据

测试代码:

	RecyclerView recycler = findViewById(R.id.recycler);

        recycler.setLayoutManager(new LinearLayoutManager(this));

        ArrayList<SectionBean> list = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            if (i == 0) {
                list.add(new SectionBean(true," 头布局 "+i));
            }else{
                list.add(new SectionBean(false,"老刘  "+i));
            }
        }

        SectionAdapter adapter = new SectionAdapter(
                R.layout.section_item1_layout,
                R.layout.section_item2_layout,
                list
        );
        recycler.setAdapter(adapter);

SectionBean实体类:

public class SectionBean extends SectionEntity<MediaStore.Video> {
    private String name;

    /**
     *
     * @param isHeader    是否是多布局
     * @param header    参数name
     */
    public SectionBean(boolean isHeader, String header) {
        super(isHeader, header);
        this.name = header;
    }
    public SectionBean(MediaStore.Video t) {
        super(t);
    }
    public String getName() {
        return name;
    }
}

这里需要注意的就是:

  • SectionBean 需要继承自SectionEntity<MediaStore.Video>
  • SectionBean 有参构造中 isHeader 表示是否是头布局(true是头布局)

效果图(3.19):

\

普通使用的内些属性,这里也同样适用哦

这个比较简单,就不啰嗦了!

(底部会给出完整代码)

多布局适配器

MultipleItemQuickAdapter适配器:

public class MultipleItemQuickAdapter extends BaseMultiItemQuickAdapter<MultipleBean, BaseViewHolder> {

    public static final int TEXT = 1;//布局一
    public static final int IMG = 2;//布局二
    public static final int TEXT_IMG = 3;//布局三
    
    public MultipleItemQuickAdapter(List data) {
        super(data);
        addItemType(TEXT, R.layout.mult_item1_layout);
        addItemType(IMG, R.layout.mult_item2_layout);
        addItemType(TEXT_IMG, R.layout.mult_item3_layout);
    }

    @Override
    protected void convert(BaseViewHolder helper, MultipleBean item) {
        switch (helper.getItemViewType()) {
            case TEXT:
                helper.setText(R.id.tv, "我是布局一 ");
                break;
            case IMG:
                helper.setImageResource(R.id.image, R.drawable.ic_launcher_background);
                break;
            case TEXT_IMG:
                helper.setImageResource(R.id.image, R.drawable.ic_launcher_foreground);
                helper.setText(R.id.tv, "我是布局三");
                break;

        }
    }
}

BaseMultiItemQuickAdapter泛型介绍:

  • 参数一:MultipleBean实体类,需要显示的数据
  • 参数二:BaseViewHolder

BaseMultiItemQuickAdapter参数介绍:

  • 参数一:数据

MultipleBean 实体类:

public class MultipleBean implements MultiItemEntity {
    private int itemType;

    public MultipleBean(int itemType) {
        this.itemType = itemType;
    }
    @Override//返回当前显示布局
    public int getItemType() {
        return itemType;
    }
}

MultipleBean需要实现MultiItemEntity接口,重写getItemType()方法,getItemType()是返回当前显示布局

测试代码:

RecyclerView recycler = findViewById(R.id.recycler);

        recycler.setLayoutManager(new LinearLayoutManager(this));

//        //初始化数据
        ArrayList<MultipleBean> list = new ArrayList<>();
        for (int i = 0; i <50; i++) {
            if (i % 3 == 0) {
                //布局一
                list.add( new MultipleBean(MultipleItemQuickAdapter.TEXT));
            }else if(i % 3 ==1){
                //布局二
                list.add( new MultipleBean(MultipleItemQuickAdapter.IMG));
            }else{
                //布局三
                list.add( new MultipleBean(MultipleItemQuickAdapter.TEXT_IMG));
            }
        }

        MultipleItemQuickAdapter adapter = new MultipleItemQuickAdapter(list);

        recycler.setAdapter(adapter);

效果图(3.20):

\

(底部会给出完整代码)

拖拽/删除适配器

DragAdapter适配器:

public class DragAdapter extends BaseItemDraggableAdapter<DragBean, BaseViewHolder> {
    /**
     *
     * @param layoutResId item布局
     * @param data  数据
     */
    public DragAdapter(int layoutResId, List<DragBean> data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, DragBean item) {
        helper.setText(R.id.tv,item.getName());
    }
}

BaseItemDraggableAdapter泛型介绍:

  • 参数一:DragBean实体类
  • 参数二:BaseViewHolder

BaseItemDraggableAdapter参数介绍:

  • 参数一:layoutResId Item布局
  • 参数二:数据

DragBean实体类 (不需要继承任何东西):

public class DragBean {
    String name;

    public String getName() {
        return name;
    }
    public DragBean(String name) {
        this.name = name;
    }
}

测试代码:

RecyclerView recycler = findViewById(R.id.recycler);

        recycler.setLayoutManager(new LinearLayoutManager(this));

        ArrayList<DragBean> list = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            list.add(new DragBean("石家庄加油~ "+i));
        }
        recycler.setAdapter(adapter = new DragAdapter(R.layout.item_layout,list));

效果图(3.21):

拖拽

	 /**
     * 拖动
     */
    private void initDrag(RecyclerView recycler) {
        ItemDragAndSwipeCallback itemDragAndSwipeCallback = new ItemDragAndSwipeCallback(adapter);

        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemDragAndSwipeCallback);
        
        itemTouchHelper.attachToRecyclerView(recycler);
        //拖拽监听
        OnItemDragListener onItemDragListener = new OnItemDragListener() {
            @Override   //开始拖拽下标
            public void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos){
                Log.i("拖拽:onItemDragStart",pos+"");
            }
            @Override//拖拽过程中 form 当前 to 拖拽到
            public void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to) {
                Log.i("拖拽:onItemDragStart",from+"\t"+to);
            }
            @Override   //结束拖拽下标
            public void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos) {
                Log.i("拖拽:onItemDragEnd",pos+"");
            }
        };
        // 开启拖拽
        adapter.enableDragItem(itemTouchHelper, R.id.tv, true);

		//拖拽监听
        adapter.setOnItemDragListener(onItemDragListener);
    }

adapter.enableDragItem()参数介绍:

  • 参数一:itemTouchHelper固定写法
  • 参数二:当前拖动的布局
  • 参数三:是否可以删除,(如果您要也想删除,这里必须填true)

OnItemDragListener拖拽监听方法介绍:

  • 方法一:onItemDragStart():开始拖拽下标(最先显示)
  • 方法二:onItemDragMoving():现在拖拽的位置,比如1->2 或者3-4
  • 方法三:onItemDragEnd() 结束拖拽的下标(最后显示)

效果图(3.22):

删除

		//删除 监听
        OnItemSwipeListener onItemSwipeListener = new OnItemSwipeListener() {
            @Override //删除元素 不管是否删除都会走这个方法
            public void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int pos) {
                Log.i("删除:onItemSwipeStart",pos+"");
            }
            @Override//不知道是干嘛的
            public void clearView(RecyclerView.ViewHolder viewHolder, int pos) {
                Log.i("删除:clearView",pos+"");
            }
            @Override//删除元素,只有删除成功才会走这个方法
            public void onItemSwiped(RecyclerView.ViewHolder viewHolder, int pos) {
                Log.i("删除:onItemSwiped",pos+"");
            }

            @Override       //v  X轴滑动距离
                            // 1 Y轴滑动距离
                            // b是否按压 true按压 false 未按压
            public void onItemSwipeMoving(Canvas canvas, RecyclerView.ViewHolder viewHolder, float v, float v1, boolean b) {
                Log.i("删除:onItemSwipeMoving",v+"\t"+v1+"\t"+b);
            }
        };
        // 开启滑动删除
        adapter.enableSwipeItem();
        //删除监听
        adapter.setOnItemSwipeListener(onItemSwipeListener);

OnItemSwipeListener()方法介绍:

  • 方法一:onItemSwipeStart删除元素 不管是否删除都会走这个方法
  • 方法二:clearView()不知道是干嘛的,总是返回-1
  • 方法三:onItemSwiped()删除元素,只有删除成功才会走这个方法
  • 方法四:onItemSwipeMoving() 手指按压的位置,以及是否按压

效果图(3.23):

\

(底部会给出完整代码)

多级列表

这里以三级列表举例

ExpandableItemAdapter多级列表适配器:

public class ExpandableItemAdapter extends BaseMultiItemQuickAdapter<MultiItemEntity, BaseViewHolder> {
    //年级
    public final static int GRADE = 0;
    //组员
    public final static int GROUP = 1;
    //姓名
    public final static int NAME = 2;
    public ExpandableItemAdapter(List<MultiItemEntity> data) {
        super(data);
        addItemType(GRADE, R.layout.item_layout);
        addItemType(GROUP, R.layout.mult_item1_layout);
        addItemType(NAME, R.layout.item_head_layout);
    }

    @Override
    protected void convert(final BaseViewHolder holder, final MultiItemEntity item) {

        switch (holder.getItemViewType()) {
            case GRADE:
                LeveBean1 leveBean1 = (LeveBean1) item;
                holder.setText(R.id.tv, leveBean1.getGrade());
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        int pos = holder.getAdapterPosition();
                        Toast.makeText(mContext, "点击了" + pos, Toast.LENGTH_SHORT).show();

                        if (leveBean1.isExpanded()) {
                            collapse(pos);
                        } else {
                            expand(pos);
                        }
                    }
                });
                break;
            case GROUP:
                LeveBean2 leveBean2 = (LeveBean2) item;
                holder.setText(R.id.tv, leveBean2.getGroup());

                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        int pos = holder.getAdapterPosition();
                        Toast.makeText(mContext, "点击了" + pos, Toast.LENGTH_SHORT).show();

                        if (leveBean2.isExpanded()) {
                            collapse(pos);
                        } else {
                            expand(pos);
                        }
                    }
                });
                break;
            case NAME:
                LeveBean3 leveBean3 = (LeveBean3) item;
                holder.setText(R.id.tv, leveBean3.getName());

                //删除某一个元素
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        int pos = holder.getAdapterPosition();
                        remove(pos);
                    }
                });
                break;
            default:
                break;
        }
    }
}

BaseMultiItemQuickAdapter泛型介绍:

  • 泛型一:MultiItemEntity接口,传递的是具体实现类
  • 泛型二:BaseViewHolder

常用方法:

  • holder.getAdapterPosition();获取适配器下标
  • expand()展开
  • collapse()缩放

LeveBean1一级实体类:

public class LeveBean1 extends AbstractExpandableItem<LeveBean2> implements MultiItemEntity {
    String grade;

    public LeveBean1(String grade) {
        this.grade = grade;
    }

    @Override
    public int getLevel() {
        return 1;
    }
    public String getGrade() {
        return grade;
    }
    @Override
    public int getItemType() {
        return GRADE;
    }
}

继承自AbstractExpandableItem,泛型为你要包裹的,这里包裹二级列表,并实现MultiItemEntity 方法,重写getLevel() 和 getItemType() 方法

  • getLevel() 当前是几级列表
  • getItemType() 当前显示的布局 GRADE = 0

LeveBean2 二级实体类:

public class LeveBean2 extends AbstractExpandableItem<LeveBean3> implements MultiItemEntity {
    String  group;

    public LeveBean2(String group) {
        this.group = group;
    }
    public String getGroup() {
        return group;
    }
    @Override
    public int getItemType() {
        return GROUP;
    }
    @Override
    public int getLevel() {
        return 2;
    }
}

和一级实体类一样,二级实体类包裹三级实体类,

LeveBean3三级实体类:

public class LeveBean3 implements MultiItemEntity{
    String name;

    public LeveBean3(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public int getItemType() {
        return NAME;
    }
}

三级实体类是最小的实体类,不用包裹,实现MultiItemEntity接口即可.

测试代码:

	    RecyclerView recycler = findViewById(R.id.recycler);

        recycler.setLayoutManager(new LinearLayoutManager(this));

        //初始化数据
        initData(3,4,5);

        //设置列表默认动画效果
        recycler.setItemAnimator(new DefaultItemAnimator());

        ExpandableItemAdapter adapter = new ExpandableItemAdapter(list);

        recycler.setAdapter(adapter);

        //默认展开一级标题
        adapter.expandAll(0,true);

        //动画
        adapter.openLoadAnimation(BaseQuickAdapter.ALPHAIN);


/**
     *
     * @param a  一级标题数量
     * @param b   二级标题数量
     * @param c   三级标题数量
     */
    private void initData(int a, int b, int c) {
        for (int i = 0; i < a; i++) {
            LeveBean1 item0 = new LeveBean1("一级列表标题" + i);
            for (int j = 0; j < b; j++) {
                LeveBean2 item1 = new LeveBean2("二级列表标题" + j);
                for (int k = 0; k < c; k++) {
                    item1.addSubItem(new LeveBean3("三级列表标题" + k));
                }
                item0.addSubItem(item1);
            }
            list.add(item0);
        }
    }

效果图(3.24):

\

完整代码

原创不易,您的点赞就是对我最大的支持哦~记得点赞 :>