框架引入

build.gradle(Project:XXXX):

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

build.gradle(Module:app):

implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.31' 




混淆

keep class com.chad.library.adapter.** {
*;
}
-keep public class * extends com.chad.library.adapter.base.BaseQuickAdapter
-keep public class * extends com.chad.library.adapter.base.BaseViewHolder
-keepclassmembers  class **$** extends com.chad.library.adapter.base.BaseViewHolder {
     <init>(...);
}




简单使用

public class Adapter1  extends BaseQuickAdapter<Student,BaseViewHolder>{

    private Context mcontext;

    public Adapter1(Context context,int layoutResId, @Nullable List<Student> data) {
        super(layoutResId, data);
        mcontext=context;
    }

    @Override
    protected void convert(BaseViewHolder helper, Student item) {

        helper.setText(R.id.student_name,item.getName())
                .setText(R.id.student_age,item.getAge()+"")
                .setText(R.id.student_address,item.getAddress());
            
        Glide.with(mcontext).load(item.getIcon()).into((ImageView) helper.getView(R.id.student_icon));
    }

}

1、使用: 首先需要继承BaseQuickAdapter,然后BaseQuickAdapter <Bean,BaseViewHolder>, 第一个泛型Bean是数据实体类型,第二个BaseViewHolder是ViewHolder其目的是为了支持扩展ViewHolder。

2、赋值:可以直接使用viewHolder对象点相关方法通过传入viewId和数据进行,方法支持链式调用。如果是加载网络图片或自定义view可以通过viewHolder.getView(viewId)获取该控件。




Item事件

adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                Toast.makeText(CommonAdapterActivity.this, "点击了item", Toast.LENGTH_SHORT).show();
            }
        });
adapter.setOnItemLongClickListener(new BaseQuickAdapter.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(BaseQuickAdapter adapter, View view, int position) {
                  Toast.makeText(CommonAdapterActivity.this, "长按了item", Toast.LENGTH_SHORT).show();
                return false;
            }
        });

注意:嵌套recycleView的情况下需要使用你使用 adapter. setOnItemClickListener 来设置点击事件,如果使用recycleView.addOnItemTouchListener会累计添加的。




Item子控件点击事件

 	@Override
    protected void convert(BaseViewHolder helper, Student item) {

        helper.setText(R.id.student_name,item.getName())
                .setText(R.id.student_age,item.getAge()+"")
                .setText(R.id.student_address,item.getAddress())
                .addOnClickListener(R.id.student_icon)
                .addOnClickListener(R.id.student_name)
                .addOnLongClickListener(R.id.student_address);

        Glide.with(mcontext).load(item.getIcon()).into((ImageView) helper.getView(R.id.student_icon));
    }
    
........................................................................................................................

adapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {

                switch (view.getId()) {

                    case R.id.student_icon:
                        //获取其他控件,如下,获取student_name
                        TextView textView=(TextView) adapter.getViewByPosition(recycleview, position, R.id.student_name);
                        Toast.makeText(CommonAdapterActivity.this, "点击"+textView.getText().toString()+"的头像", Toast.LENGTH_SHORT).show();
                        break;

                    case R.id.student_name:
                        Toast.makeText(CommonAdapterActivity.this, "点击了名字", Toast.LENGTH_SHORT).show();
                        break;
                }
            }
        });

 adapter.setOnItemChildLongClickListener(new BaseQuickAdapter.OnItemChildLongClickListener() {
            @Override
            public boolean onItemChildLongClick(BaseQuickAdapter adapter, View view, int position) {

                if (view.getId() == R.id.student_address)
                    Toast.makeText(CommonAdapterActivity.this, "长按了address", Toast.LENGTH_SHORT).show();
                return false;
            }
        });




动画

开启动画(默认为渐显效果)

adapter.openLoadAnimation();

默认提供5种方法(渐显、缩放、从下到上,从左到右、从右到左)

    public static final int ALPHAIN = 0x00000001;
    public static final int SCALEIN = 0x00000002;
    public static final int SLIDEIN_BOTTOM = 0x00000003;
    public static final int SLIDEIN_LEFT = 0x00000004;
    public static final int SLIDEIN_RIGHT = 0x00000005;

自定义动画

quickAdapter.openLoadAnimation(new BaseAnimation() {
	@Override
	public Animator[] getAnimators(View view) {
		return new Animator[]{
			ObjectAnimator.ofFloat(view, "scaleY", 1, 1.1f, 1),
            ObjectAnimator.ofFloat(view, "scaleX", 1, 1.1f, 1)
		};
	}
});

动画默认只执行一次,如果想重复执行可设置

mQuickAdapter.isFirstOnly(false);

因为有些人不希望第一页看到动画,或者说希望前几个条目加载不需要有动画,所以可以设置不显示动画数量

adapter.setNotDoAnimationCount(count);




添加头部、尾部

mQuickAdapter.addHeaderView(getView());
mQuickAdapter.addFooterView(getView());

删除指定view

mQuickAdapter.removeHeaderView(getView);
mQuickAdapter.removeFooterView(getView);

删除所有

mQuickAdapter.removeAllHeaderView();
mQuickAdapter.removeAllFooterView();

默认出现了头部就不会显示Empty,和尾部,配置以下方法也支持同时显示:

setHeaderAndEmpty
setHeaderFooterEmpty

默认头部尾部都是占满一行,如果需要不占满可以配置:

setHeaderViewAsFlow
setFooterViewAsFlow

加载更多

此adapter封装加载更多其实并不好用,因此我更建议采用传统的根据recyclerview判断item位置进行判断,自动加载更多

  recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                firstVisibleItem=linearLayoutManager.findFirstVisibleItemPosition();
                
                if (newState == RecyclerView.SCROLL_STATE_IDLE&&linearLayoutManager.getItemCount() >0&&lastVisibleItem + 1 == linearLayoutManager.getItemCount()) {
                        new Handler().postDelayed(() -> loadData(),300) ;
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                firstVisibleItem=linearLayoutManager.findFirstVisibleItemPosition();
               }
        });
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();  
//屏幕中最后一个可见子项的position
int lastVisibleItem = layoutManager.findLastVisibleItemPosition();  

//当前屏幕所看到的子项个数
layoutManager.getChildCount();  

//当前RecyclerView的所有子项个数
layoutManager.getItemCount();  

//RecyclerView的滑动状态
recyclerView.getScrollState();

如果想要预加载也很简单,只需要修改当前最下方item的postion和总条目之间的差值即可。




拖拽、滑动删除

拖拽和滑动删除的回调方法

OnItemDragListener onItemDragListener = new OnItemDragListener() {
    @Override
    public void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos){}
    @Override
    public void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to) {}
    @Override
    public void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos) {}
}

OnItemSwipeListener onItemSwipeListener = new OnItemSwipeListener() {
    @Override
    public void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int pos) {}
    @Override
    public void clearView(RecyclerView.ViewHolder viewHolder, int pos) {}
    @Override
    public void onItemSwiped(RecyclerView.ViewHolder viewHolder, int pos) {}
};

adapter需要继承BaseItemDraggableAdapter

public class MyBaseQuickAdapter extends BaseQuickAdapter<Bean, BaseViewHolder> {

    public MyBaseQuickAdapter(@Nullable List<Bean> data) {
        super(R.layout.list_item, data);
    }

    @Override
    protected void convert(@NonNull BaseViewHolder helper, Bean item) {
        helper.setText(R.id.name, item.getName())
                .setText(R.id.age, String.valueOf(item.getAge()))
                .addOnClickListener(R.id.name)
                .addOnClickListener(R.id.age)
                .addOnLongClickListener(R.id.name)
                .addOnLongClickListener(R.id.age);
    }
}

Activity使用代码

mAdapter = new ItemDragAdapter(mData);
ItemDragAndSwipeCallback itemDragAndSwipeCallback = new ItemDragAndSwipeCallback(mAdapter);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemDragAndSwipeCallback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);

// 开启拖拽
mAdapter.enableDragItem(itemTouchHelper, R.id.textView, true);
mAdapter.setOnItemDragListener(onItemDragListener);

// 开启滑动删除
mAdapter.enableSwipeItem();
mAdapter.setOnItemSwipeListener(onItemSwipeListener);

默认不支持多个不同的 ViewType 之间进行拖拽,如果开发者有所需求:
重写ItemDragAndSwipeCallback里的onMove()方法,return true即可

完整使用

public class MyBaseQuickAdapter extends BaseItemDraggableAdapter<Bean, BaseViewHolder> {

    public MyBaseQuickAdapter(@Nullable List<Bean> data) {
        super(R.layout.list_item, data);
    }

    @Override
    protected void convert(@NonNull BaseViewHolder helper, Bean item) {
        helper.setText(R.id.name, item.getName())
                .setText(R.id.age, String.valueOf(item.getAge()))
                .addOnClickListener(R.id.name)
                .addOnClickListener(R.id.age)
                .addOnLongClickListener(R.id.name)
                .addOnLongClickListener(R.id.age);
    }

}
        adapter = new MyBaseQuickAdapter(data);
        adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                Toast.makeText(MainActivity.this, "点击了" + position, Toast.LENGTH_SHORT).show();
            }
        });
        adapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                switch (view.getId()) {
                    case R.id.name:
                        Toast.makeText(MainActivity.this, "点击了name", Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.age:
                        Toast.makeText(MainActivity.this, "点击了age", Toast.LENGTH_SHORT).show();
                        break;
                }
            }
        });
        adapter.setOnItemChildLongClickListener(new BaseQuickAdapter.OnItemChildLongClickListener() {
            @Override
            public boolean onItemChildLongClick(BaseQuickAdapter adapter, View view, int position) {
                switch (view.getId()) {
                    case R.id.name:
                        Toast.makeText(MainActivity.this, "长按了name", Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.age:
                        Toast.makeText(MainActivity.this, "长按了age", Toast.LENGTH_SHORT).show();
                        break;
                }
                return false;
            }
        });
        adapter.openLoadAnimation();
        adapter.openLoadAnimation(BaseQuickAdapter.ALPHAIN);
        adapter.isFirstOnly(false);
        adapter.setNotDoAnimationCount(5);
        View headerView = View.inflate(this, R.layout.header_view, null);
        View footerView = View.inflate(this, R.layout.footer_view, null);
        adapter.addHeaderView(headerView);
        adapter.addFooterView(footerView);
        ItemDragAndSwipeCallback itemDragAndSwipeCallback = new ItemDragAndSwipeCallback(adapter);
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemDragAndSwipeCallback);
        itemTouchHelper.attachToRecyclerView(list);
        // 开启拖拽
        adapter.enableDragItem(itemTouchHelper, R.id.name, true);
        adapter.setOnItemDragListener(new OnItemDragListener() {
            @Override
            public void onItemDragStart(RecyclerView.ViewHolder viewHolder, int i) {
            }

            @Override
            public void onItemDragMoving(RecyclerView.ViewHolder viewHolder, int i, RecyclerView.ViewHolder viewHolder1, int i1) {
            }

            @Override
            public void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int i) {
            }
        });
        // 开启滑动删除
        adapter.enableSwipeItem();
        adapter.setOnItemSwipeListener(new OnItemSwipeListener() {
            @Override
            public void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int i) {
            }

            @Override
            public void clearView(RecyclerView.ViewHolder viewHolder, int i) {
            }

            @Override
            public void onItemSwiped(RecyclerView.ViewHolder viewHolder, int i) {
            }

            @Override
            public void onItemSwipeMoving(Canvas canvas, RecyclerView.ViewHolder viewHolder, float v, float v1, boolean b) {
            }
        });
        list.setAdapter(adapter);




分组布局

此adapter分组布局,不是类似于那种黏性头部的分组,而是把头布局作为一个item进行多布局的封装。
头布局也支持点击事件,头布局内部的控件也支持点击事件。和普通布局一般无二。

把需要加头布局的实体类用一个新的实体类包裹起来,比如作者举例的Video,用MySection 包裹了Video,这样的MySection内部有两个构造方法,一个是头布局的构造方法,一个是实体类的构造方法,举例如下

public class MySection extends SectionEntity<Video> {
    private boolean isMore;
    public MySection(boolean isHeader, String header, boolean isMroe) {
        super(isHeader, header);
        this.isMore = isMroe;
    }

    public MySection(Video t) {
        super(t);
    }

    public boolean isMore() {
        return isMore;
    }

    public void setMore(boolean mroe) {
        isMore = mroe;
    }
}

你可以在构造方法中加上自己需要的字段来以便给头布局赋值;上述代码加入了一个ismore字段,用来判断是否有展开更多字段。

adapter需要实现BaseSectionQuickAdapter,convertHead用来绑定头布局数据,convert用来绑定一般数据。

public class SectionAdapter extends BaseSectionQuickAdapter<MySection, BaseViewHolder> {

    public SectionAdapter(int layoutResId, int sectionHeadResId, List data) {
        super(layoutResId, sectionHeadResId, data);
    }

    @Override
    protected void convertHead(BaseViewHolder helper, final MySection item) {
        helper.setText(R.id.header, item.header)
		      .setVisible(R.id.more, item.isMore())
              .addOnClickListener(R.id.more);
    }

    @Override
    protected void convert(BaseViewHolder helper, MySection item) {
        Video video = (Video) item.t;
        switch (helper.getLayoutPosition() %
                2) {
            case 0:
                helper.setImageResource(R.id.iv, R.mipmap.m_img1);
                break;
            case 1:
                helper.setImageResource(R.id.iv, R.mipmap.m_img2);
                break;

        }
        helper.setText(R.id.tv, video.getName());
    }
}

当然数据初始化的时候要注意,同一头布局下的需要写在一起:

  public static List<MySection> getSampleData() {
  
        List<MySection> list = new ArrayList<>();
        
        list.add(new MySection(true, "Section 1", true));
        list.add(new MySection(new Video(HTTPS_AVATARS1_GITHUBUSERCONTENT_COM_LINK, CYM_CHAD)));

        list.add(new MySection(true, "Section 2", false));
        list.add(new MySection(new Video(HTTPS_AVATARS1_GITHUBUSERCONTENT_COM_LINK, CYM_CHAD)));
        list.add(new MySection(new Video(HTTPS_AVATARS1_GITHUBUSERCONTENT_COM_LINK, CYM_CHAD)));
        list.add(new MySection(new Video(HTTPS_AVATARS1_GITHUBUSERCONTENT_COM_LINK, CYM_CHAD)));
        list.add(new MySection(new Video(HTTPS_AVATARS1_GITHUBUSERCONTENT_COM_LINK, CYM_CHAD)));
        list.add(new MySection(new Video(HTTPS_AVATARS1_GITHUBUSERCONTENT_COM_LINK, CYM_CHAD)));

        list.add(new MySection(true, "Section 3", false));
        list.add(new MySection(new Video(HTTPS_AVATARS1_GITHUBUSERCONTENT_COM_LINK, CYM_CHAD)));
        list.add(new MySection(new Video(HTTPS_AVATARS1_GITHUBUSERCONTENT_COM_LINK, CYM_CHAD)));
        
        list.add(new MySection(true, "Section 4", false));
        list.add(new MySection(new Video(HTTPS_AVATARS1_GITHUBUSERCONTENT_COM_LINK, CYM_CHAD)));
        list.add(new MySection(new Video(HTTPS_AVATARS1_GITHUBUSERCONTENT_COM_LINK, CYM_CHAD)));
      
    }

多布局

实体类必须实现MultiItemEntity,在设置数据的时候,需要给每一个数据设置itemType

public class MultipleItem implements MultiItemEntity {
    public static final int TEXT = 1;
    public static final int IMG = 2;
    private int itemType;

    public MultipleItem(int itemType) {
        this.itemType = itemType;
    }

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

adapter需要继承BaseMultiItemQuickAdapter,addItemType用来绑定itemType和item布局。

public class MultipleItemQuickAdapter extends BaseMultiItemQuickAdapter<MultipleItem, BaseViewHolder> {

    public MultipleItemQuickAdapter(List data) {
        super(data);
        addItemType(1, R.layout.text_view);
        addItemType(2, R.layout.image_view);
    }

    @Override
    protected void convert(BaseViewHolder helper, MultipleItem item) {
        switch (helper.getItemViewType()) {
            case 1:
                helper.setImageUrl(R.id.tv, item.getContent());
                break;
            case 2:
                helper.setImageUrl(R.id.iv, item.getContent());
                break;
        }
    }
}




设置空布局

mQuickAdapter.setEmptyView(getView());
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐