首先来看一个图知道可以有哪些功能
依照上图可以知道BaseRecyclerViewAdapterHelper分别有的优点和功能是:
1.优化适配器减少代码
2.item项的点击事件
3.为adapter添加动画效果
4.为recyclerview(或adapter)添加header和footer布局
5.对item进行点击拖动
6.自动加载数据
7.实现多级联动
8.可以自定义实现多类型布局
9.设置布局的加载方式:如加载错误,成功,失败,空数据时显示不同界面
为BaseRecyclerViewAdapterHelper为其配置和导入依赖
在 build.gradle 的 repositories 添加:
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
然后在dependencies中添加依赖
compile 'com.android.support:recyclerview-v7:25.3.1'
compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.23'
官方地址:https://github.com/CymChad/BaseRecyclerViewAdapterHelper
1.首先来观察使用BaseQuickAdapter(这个主要是针对不实现多布局而用)的使用
public class AnimationAdapter extends BaseQuickAdapter<Status, BaseViewHolder> {///中括号中第一个参数:Java的bean,第二个参数:固定的BaseViewHolder,
public AnimationAdapter() {
super(R.layout.layout_animation, DataServer.getSampleData(100));
}
@Override
protected void convert(BaseViewHolder helper, Status item) {//实现数据绑定
helper.addOnClickListener(R.id.img).addOnClickListener(R.id.tweetName);//为控件添加点击事件,如果要在哪个控件上实现点击参数中就用哪个控件的ID
switch (helper.getLayoutPosition() %
3) {
case 0:
helper.setImageResource(R.id.img, R.mipmap.animation_img1);
break;
case 1:
helper.setImageResource(R.id.img, R.mipmap.animation_img2);
break;
case 2:
helper.setImageResource(R.id.img, R.mipmap.animation_img3);
break;
}
helper.setText(R.id.tweetName, "Hoteis in Rio de Janeiro");
String msg = "\"He was one of Australia's most of distinguished artistes, renowned for his portraits\"";
((TextView) helper.getView(R.id.tweetText)).setText(SpannableStringUtils.getBuilder(msg).append("landscapes and nedes").setClickSpan(clickableSpan).create());
((TextView) helper.getView(R.id.tweetText)).setMovementMethod(ClickableMovementMethod.getInstance());
((TextView) helper.getView(R.id.tweetText)).setFocusable(false);
((TextView) helper.getView(R.id.tweetText)).setClickable(false);
((TextView) helper.getView(R.id.tweetText)).setLongClickable(false);
}
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View widget) {
ToastUtils.showShortToast("事件触发了 landscapes and nedes");
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(Utils.getContext().getResources().getColor(R.color.clickspan_color));
ds.setUnderlineText(true);
}
};
}
Adapter调用和点击事件
这里的点击事件两种第一中是整个item设置点击事件:如果是整体item则不用再adapter中添加 helper.addOnChickListener(控件Id)如果设置了反而不能触发点击事件
我们直接用adapter.setOnItemChickLisener()就可以触发点击事件
第二种给item的某个按钮设置点击
如果我们要在item中的某一个设置点击则需要在adapter中添加helper.addOnChickListener(控件Id)这句代码
用adapter.setOnItemChildClickListenre()来设置点击事件.
mRecyclerView= (RecyclerView) findViewById(R.id.recycler);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setHasFixedSize(true);//是否重新设置计算item的高度和宽度
// list=generrateData();
initData();
initAdapter();
// mAdapter=new ExpandableItemAdapter(list);
mRecyclerView.setAdapter(mAdapter);
//mRecyclerView的点击事件同样要在adapter中使用helper.addOnClickListener(R.id.name);才能使用
/*mRecyclerView.addOnItemTouchListener(new OnItemChildClickListener() {
@Override
public void onSimpleItemChildClick(BaseQuickAdapter adapter, View view, int position) {
}
});*/
mAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
Toast.makeText(MainActivity.this, "ddd", Toast.LENGTH_SHORT).show();
}
});
2.拖动和移动删除使用
直接看代码
public class ItemDragAndSwipeUseActivity extends BaseActivity {
private static final String TAG = ItemDragAndSwipeUseActivity.class.getSimpleName();
private RecyclerView mRecyclerView;
private List<String> mData;
private ItemDragAdapter mAdapter;
private ItemTouchHelper mItemTouchHelper;//item点击帮助类
private ItemDragAndSwipeCallback mItemDragAndSwipeCallback;//item拖动回调
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_touch_use);
setBackBtn();
setTitle("ItemDrag And Swipe");
mRecyclerView = (RecyclerView) findViewById(R.id.rv_list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mData = generateData(50);
OnItemDragListener listener = new OnItemDragListener() {
//item开始拖动
@Override
public void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos) {
Log.d(TAG, "drag start");
BaseViewHolder holder = ((BaseViewHolder) viewHolder);
// holder.setTextColor(R.id.tv, Color.WHITE);
}
//item开始移动
@Override
public void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to) {
Log.d(TAG, "move from: " + source.getAdapterPosition() + " to: " + target.getAdapterPosition());
}
//itme拖动结束
@Override
public void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos) {
Log.d(TAG, "drag end");
BaseViewHolder holder = ((BaseViewHolder) viewHolder);
// holder.setTextColor(R.id.tv, Color.BLACK);
}
};
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(20);
paint.setColor(Color.BLACK);
OnItemSwipeListener onItemSwipeListener = new OnItemSwipeListener() {
@Override
public void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int pos) {
Log.d(TAG, "view swiped start: " + pos);
BaseViewHolder holder = ((BaseViewHolder) viewHolder);
// holder.setTextColor(R.id.tv, Color.WHITE);
}
@Override
public void clearView(RecyclerView.ViewHolder viewHolder, int pos) {
Log.d(TAG, "View reset: " + pos);
BaseViewHolder holder = ((BaseViewHolder) viewHolder);
// holder.setTextColor(R.id.tv, Color.BLACK);
}
@Override
public void onItemSwiped(RecyclerView.ViewHolder viewHolder, int pos) {
Log.d(TAG, "View Swiped: " + pos);
}
@Override
public void onItemSwipeMoving(Canvas canvas, RecyclerView.ViewHolder viewHolder, float dX, float dY, boolean isCurrentlyActive) {
canvas.drawColor(ContextCompat.getColor(ItemDragAndSwipeUseActivity.this, R.color.color_light_blue));
// canvas.drawText("Just some text", 0, 40, paint);
}
};
mAdapter = new ItemDragAdapter(mData);
mItemDragAndSwipeCallback = new ItemDragAndSwipeCallback(mAdapter);//在adapter上进行操作
mItemTouchHelper = new ItemTouchHelper(mItemDragAndSwipeCallback);//绑定mItemDragAndSwipeCallback
mItemTouchHelper.attachToRecyclerView(mRecyclerView);//mItemTouchHelper绑定到recyclerview
//mItemDragAndSwipeCallback.setDragMoveFlags(ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT | ItemTouchHelper.UP | ItemTouchHelper.DOWN);
mItemDragAndSwipeCallback.setSwipeMoveFlags(ItemTouchHelper.START | ItemTouchHelper.END);//设置左右删除item
mAdapter.enableSwipeItem();//刷新结束回调
mAdapter.setOnItemSwipeListener(onItemSwipeListener);//绑定onItemSwipeListener
mAdapter.enableDragItem(mItemTouchHelper);//绑定mItemTouchHelper
mAdapter.setOnItemDragListener(listener);
// mRecyclerView.addItemDecoration(new GridItemDecoration(this ,R.drawable.list_divider));
mRecyclerView.setAdapter(mAdapter);
// mRecyclerView.addOnItemTouchListener(new OnItemClickListener() {
// @Override
// public void onSimpleItemClick(final BaseQuickAdapter adapter, final View view, final int position) {
// ToastUtils.showShortToast("点击了" + position);
// }
// });
mAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
ToastUtils.showShortToast("点击了" + position);
}
});
}
private List<String> generateData(int size) {
ArrayList<String> data = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
data.add("item " + i);
}
return data;
}
}
public class ItemDragAdapter extends BaseItemDraggableAdapter<String, BaseViewHolder> {
public ItemDragAdapter(List data) {
super(R.layout.item_draggable_view, data);
}
@Override
protected void convert(BaseViewHolder helper, String item) {
switch (helper.getLayoutPosition() %
3) {
case 0:
helper.setImageResource(R.id.iv_head, R.mipmap.head_img0);
break;
case 1:
helper.setImageResource(R.id.iv_head, R.mipmap.head_img1);
break;
case 2:
helper.setImageResource(R.id.iv_head, R.mipmap.head_img2);
break;
}
helper.setText(R.id.tv, item);
}
}
如果要使用动画直接调用
mAnimationAdapter.openLoadAnimation();
这个方法即可
3.实现多级联动
实现多级联动必须让JavaBean继承AbstaractExpandaleItem<T>类(这里T写的是你的下一级的JavaBean类)和继承接口,要实现多少级由自己决定
一级标题类
public class Level0Item extends AbstractExpandableItem<Level1Item> implements MultiItemEntity {
public String title;
public String subTitle;
public Level0Item( String title, String subTitle) {
this.subTitle = subTitle;
this.title = title;
}
@Override
public int getItemType() {
return ExpandableItemAdapter.TYPE_LEVEL_0;
}
@Override
public int getLevel() {
return 0;
}
}
二级标题类
public class Level1Item extends AbstractExpandableItem<Person> implements MultiItemEntity{
public String title;
public String subTitle;
public Level1Item(String title, String subTitle) {
this.subTitle = subTitle;
this.title = title;
}
@Override
public int getItemType() {
return ExpandableItemAdapter.TYPE_LEVEL_1;
}
@Override
public int getLevel() {
return 1;
}
}
三级内容
public class Person implements MultiItemEntity{
public Person(String name, int age) {
this.age = age;
this.name = name;
}
public String name;
public int age;
@Override
public int getItemType() {
return ExpandableItemAdapter.TYPE_PERSON;
}
}
使用代码:
public class ExpandableUseActivity extends BaseActivity {
RecyclerView mRecyclerView;
ExpandableItemAdapter adapter;
ArrayList<MultiItemEntity> list;//创建一个父类MultiItemEntity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setBackBtn();
setTitle("ExpandableItem Activity");
setContentView(R.layout.activity_expandable_item_use);
mRecyclerView = (RecyclerView) findViewById(R.id.rv);
list = generateData();
adapter = new ExpandableItemAdapter(list);
final GridLayoutManager manager = new GridLayoutManager(this, 3);
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {//设置recyclerview的显示格式
@Override
public int getSpanSize(int position) {
/**
* 如果adapter.getItemViewType(position)获得类型==ExpandableItemAdapter.TYPE_PERSON时就返回1:表示recyclerview只显示一列,否则显示manager.getSpanCount()这么多列
*/
return adapter.getItemViewType(position) == ExpandableItemAdapter.TYPE_PERSON ? 1 : manager.getSpanCount();
}
});
mRecyclerView.setAdapter(adapter);
// important! setLayoutManager should be called after setAdapter
mRecyclerView.setLayoutManager(manager);
adapter.expandAll();
}
private ArrayList<MultiItemEntity> generateData() {
int lv0Count = 9;
int lv1Count = 3;
int personCount = 5;
String[] nameList = {"Bob", "Andy", "Lily", "Brown", "Bruce"};
Random random = new Random();
ArrayList<MultiItemEntity> res = new ArrayList<>();
for (int i = 0; i < lv0Count; i++) {//添加一级标题内容
Level0Item lv0 = new Level0Item("This is " + i + "th item in Level 0", "subtitle of " + i);
for (int j = 0; j < lv1Count; j++) {//添加二级标题
Level1Item lv1 = new Level1Item("Level 1 item: " + j, "(no animation)");
for (int k = 0; k < personCount; k++) {//三级内容
lv1.addSubItem(new Person(nameList[k], random.nextInt(40)));//将三级内容联动到二级下
}
lv0.addSubItem(lv1);//将二级标题联动到一级标题下
}
res.add(lv0);//最后添加到ArrayList<MultiItemEntity> res = new ArrayList<>();中
}
return res;
}
}
adapter
public class ExpandableItemAdapter extends BaseMultiItemQuickAdapter<MultiItemEntity, BaseViewHolder> {
private static final String TAG = ExpandableItemAdapter.class.getSimpleName();
public static final int TYPE_LEVEL_0 = 0;
public static final int TYPE_LEVEL_1 = 1;
public static final int TYPE_PERSON = 2;
/**
* Same as QuickAdapter#QuickAdapter(Context,int) but with
* some initialization data.
*
* @param data A new list is created out of this one to avoid mutable list
*/
public ExpandableItemAdapter(List<MultiItemEntity> data) {//为其设置三级标题类型
super(data);
addItemType(TYPE_LEVEL_0, R.layout.item_expandable_lv0);
addItemType(TYPE_LEVEL_1, R.layout.item_expandable_lv1);
addItemType(TYPE_PERSON, R.layout.item_expandable_lv2);
}
@Override
protected void convert(final BaseViewHolder holder, final MultiItemEntity item) {
switch (holder.getItemViewType()) {
case TYPE_LEVEL_0://一级标题
switch (holder.getLayoutPosition() %
3) {
case 0:
holder.setImageResource(R.id.iv_head, R.mipmap.head_img0);
break;
case 1:
holder.setImageResource(R.id.iv_head, R.mipmap.head_img1);
break;
case 2:
holder.setImageResource(R.id.iv_head, R.mipmap.head_img2);
break;
}
//绑定数据
final Level0Item lv0 = (Level0Item)item;
holder.setText(R.id.title, lv0.title)
.setText(R.id.sub_title, lv0.subTitle)
.setImageResource(R.id.iv, lv0.isExpanded() ? R.mipmap.arrow_b : R.mipmap.arrow_r);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = holder.getAdapterPosition();
Log.d(TAG, "Level 0 item pos: " + pos);
if (lv0.isExpanded()) {
collapse(pos);
} else {
// if (pos % 3 == 0) {
// expandAll(pos, false);
// } else {
expand(pos);
// }
}
}
});
break;
case TYPE_LEVEL_1://二级同理
final Level1Item lv1 = (Level1Item)item;
holder.setText(R.id.title, lv1.title)
.setText(R.id.sub_title, lv1.subTitle)
.setImageResource(R.id.iv, lv1.isExpanded() ? R.mipmap.arrow_b : R.mipmap.arrow_r);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = holder.getAdapterPosition();
Log.d(TAG, "Level 1 item pos: " + pos);
if (lv1.isExpanded()) {
collapse(pos, false);
} else {
expand(pos, false);
}
}
});
break;
case TYPE_PERSON://三级
final Person person = (Person)item;
holder.setText(R.id.tv, person.name + " parent pos: " + getParentPosition(person));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int cp = getParentPosition(person);
((Level1Item)getData().get(cp)).removeSubItem(person);
getData().remove(holder.getLayoutPosition());
notifyItemRemoved(holder.getLayoutPosition());
}
});
break;
}
}
}
4.多布局的实现首先JavaBean类继承MultiItemEntity接口重写getItemType()方法这里返回的就是布局的类型,可以根据JavaBean中的type来实现不同布局
public class Person implements MultiItemEntity{
private String name;
private String age;
private int img;
private int type;
public Person(String name, String age, int img) {
this.name = name;
this.age = age;
this.img = img;
}
public Person(String name, String age, int img, int type) {
this.name = name;
this.age = age;
this.img = img;
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public int getImg() {
return img;
}
public void setImg(int img) {
this.img = img;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
@Override
public int getItemType() {
return this.type;//type根据上面的构造函数来传入不通的值实现多类型的实现
}
}
重写Adapter类继承BaseMultiItemQuickAdapter
public class PerserAapter extends BaseMultiItemQuickAdapter<Person, BaseViewHolder> {
/**
* 定义不同布局的类型ID
*/
public static final int TYPE_HEAD = 0;
public static final int TYPE_MIDDLE = 1;
public static final int TYPE_FOOT = 2;
public PerserAapter(List<Person> data) {
super(data);
/**
* 根据不同类型ID实现不同布局,后面跟上的就是不同的布局
*/
addItemType(TYPE_HEAD, R.layout.item1);
addItemType(TYPE_MIDDLE, R.layout.item2);
addItemType(TYPE_FOOT, R.layout.item3);
}
@Override
protected void convert(BaseViewHolder helper, Person item) {
/***
* 获取类型值来绑定数据
*/
switch (helper.getItemViewType()) {
case TYPE_HEAD:
helper.setText(R.id.name,item.getName()).setText(R.id.age,item.getAge());
break;
case TYPE_MIDDLE:
helper.setText(R.id.name,item.getName()).setText(R.id.age,item.getAge());
break;
case TYPE_FOOT:
helper.setText(R.id.name,item.getName()).setText(R.id.age,item.getAge());
break;
}
}
}
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private PerserAapter mAapter;
private List<Person>mData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView= (RecyclerView) findViewById(recycler);
GridLayoutManager gridLayoutManager=new GridLayoutManager(this,3);
mRecyclerView.setLayoutManager(gridLayoutManager);
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (position%2==0)
return 3;
return 1;
}
});
initData();
mAapter=new PerserAapter(mData);
mRecyclerView.setAdapter(mAapter);
}
private void initData() {
mData=new ArrayList<>();
for (int i = 0; i < 5; i++) {
Person person=new Person("nama"+i,"age"+i,0,PerserAapter.TYPE_HEAD);//初始化数据的同时传入类型ID
mData.add(person);
}
for (int i = 0; i < 2; i++) {
Person person=new Person("nama"+i,"age"+i,0,PerserAapter.TYPE_MIDDLE);
mData.add(person);
}
for (int i = 0; i < 3; i++) {
Person person = new Person("nama" + i, "age" + i, 0, PerserAapter.TYPE_FOOT);
mData.add(person);
}
}
}