转载:https://www.jianshu.com/p/4f9591291365
RecyclerView是什么:
从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,可以用来代替传统的ListView,更加强大和灵活。RecyclerView的官方定义如下:
RecyclerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能,这一点从它的名字Recyclerview即回收view也可以看出。
- RecyclerView封装了viewholder的回收复用,也就是说RecyclerView标准化了ViewHolder,编写Adapter面向的是ViewHolder而不再是View了,复用的逻辑被封装了,写起来更加简单。
直接省去了listview中convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。 - 提供了一种插拔式的体验,高度的解耦,异常的灵活,针对一个Item的显示RecyclerView专门抽取出了相应的类,来控制Item的显示,使其的扩展性非常强。
- 设置布局管理器以控制Item的布局方式,横向、竖向以及瀑布流方式
例如:你想控制横向或者纵向滑动列表效果可以通过LinearLayoutManager这个类来进行控制(与GridView效果对应的是GridLayoutManager,与瀑布流对应的还StaggeredGridLayoutManager等)。也就是说RecyclerView不再拘泥于ListView的线性展示方式,它也可以实现GridView的效果等多种效果。 - 可设置Item的间隔样式(可绘制)
通过继承RecyclerView的ItemDecoration这个类,然后针对自己的业务需求去书写代码。 - 可以控制Item增删的动画,可以通过ItemAnimator这个类进行控制,当然针对增删的动画,RecyclerView有其自己默认的实现。
但是关于Item的点击和长按事件,需要用户自己去实现。
基本使用
1.基础代码和布局
1.导入包:
compile group: 'com.android.support', name: 'recyclerview-v7', version: '25.0.1'
2.布局界面设置RecyclerView
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView_body"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</RelativeLayout>
3.设置样式LayoutManger
//列表配置
mRecyclerView = ((RecyclerView) findViewById(R.id.recyclerView));
//设置显示样式
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
4.设置适配器加载视图和数据(Adapter)
newTableAdaper = new NewTableAdapter(this, hasNumMap);
mRecyclerView.setAdapter(newTableAdaper);
2.自定义Adapter
1.新建一个adapter,继承RecylerView.Adapter<ViewHolder>
(注意:因为区分主题和视图展示view这里的viewholder说个基类)
public class NewTableAdapter extends RecyclerView.Adapter<BaseMulViewHolder>
BaseMulViewHolder继承viewhodler,viewholder可以看成是加载视图的一个封装对象(如图一),当然也可以帮这个对象添加自己的一些属性,通过继承自己定义的实体类属性获得它的属性(如图二)(注:自己了解下泛型)。
图一:
public abstract class BaseMulViewHolder<T extends BaseMulDataModel> extends RecyclerView.ViewHolder {
public BaseMulViewHolder(View itemView) {
super(itemView);
}
//自己添加的抽象方法
public abstract void bindData(T dataModel, int position);
}
图二:
public class BaseMulDataModel {
private int type;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
2.重写方法
(因为要标题视图和展示视图分类,所以要重写getItemType())
public class MyRecyclerViewAdapetr extends RecyclerView.Adapter<BaseMulViewHolder>{
@Override
public BaseMulViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(BaseMulViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
@Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
}
当setAdapter执行的时候执行getItemViewType来进行类型判断,返回到OnCreateViewHolder,然后再通过OnCreateViewHolder拿到viewType进行加载视图,其实下面的分分类是应该通过mList获取里面的type来判断的,这里复杂了
List<BaseMulDataModel> mList;//存放数据
@Override
public int getItemViewType(int position) {
if (mList.get(position) instanceof TitleModel) {
return TYPE_Title;
} else {
return TYPE_View;
}
}
然后再onCreateViewHolder中进行分类判断,根据不同的type,新建出不同的viewHolder:
@Override
public BaseMulViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_Title:
return new ViewHolderTitle(LayoutInflater.from(parent.getContext())
.inflate(R.layout.newtable_itemcard_title, parent, false));
case TYPE_View:
return new ViewHolderView(LayoutInflater.from(parent.getContext())
.inflate(R.layout.newtable_itemcard_view, parent, false));
}
return null;
}
根据上面的逻辑,新加了两个继承自BaseMulViewHolder 的子类viewHolder
/**
* 设置第一个布局的数据
*/
class ViewHolderTitle extends BaseMulViewHolder<TitleModel> {
TextView textView;
Button btn_rowfull;
public ViewHolderTitle(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.row_name);
btn_rowfull = (Button) itemView.findViewById(R.id.btn_rowfull);
}
@Override
public void bindData(final TitleModel dataModel, int position) {
textView.setText(dataModel.getTitle());
btn_rowfull.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Row = dataModel.getRow();
for (int i = COL * (Row - 1); i <= COL * Row - 1; i++) {
notifyItemChanged(i);
}
}
});
}
}
/**
* 设置第一个布局的数据
*/
class ViewHolderView extends BaseMulViewHolder<DataViewModel> {
TextView col_no;
TextView col_name;
TextView col_count;
TextView col_hasnum;
ImageView imgicon;
ImageButton btnadd;
ImageButton btnreduce;
Button btnfull;
public ViewHolderView(View itemView) {
super(itemView);
col_no = (TextView) itemView.findViewById(R.id.col_no);
col_name = (TextView) itemView.findViewById(R.id.col_name);
col_count = (TextView) itemView.findViewById(R.id.col_count);
col_hasnum = (TextView) itemView.findViewById(R.id.col_hasnum);
btnadd = (ImageButton) itemView.findViewById(R.id.btnadd);
btnreduce = (ImageButton) itemView.findViewById(R.id.btnreduce);
btnfull = (Button) itemView.findViewById(R.id.btnfull);
imgicon = ((ImageView) itemView.findViewById(R.id.img_icon));
}
@Override
public void bindData(final DataViewModel dataModel, final int position) {
Glide.with(mContext).load(dataModel.getImg_url()).into(imgicon);
col_no.setText(dataModel.getNo());
col_name.setText(dataModel.getPrduceName());
col_count.setText("" + dataModel.getCount());
//这个不能删除,要判断行数,用于一行不忙
if (dataModel.getRow() == Row) {
col_hasnum.setText("" + dataModel.getCount());
int newhasNum = Integer.valueOf(col_hasnum.getText().toString());
addMap(dataModel, newhasNum);
} else {
int hasNum = getdataMap(dataModel);
if (hasNum == -1) {
col_hasnum.setText("" + dataModel.getHasNum());
} else {
col_hasnum.setText("" + hasNum);
}
}
btnfull.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
initRow();
col_hasnum.setText("" + dataModel.getCount());
int newhasNum = Integer.valueOf(col_hasnum.getText().toString());
addMap(dataModel, newhasNum);
}
});
btnadd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
initRow();
int hasNum = Integer.valueOf(col_hasnum.getText().toString());
if (hasNum < 15) {
col_hasnum.setText("" + (hasNum + 1));
} else {
col_hasnum.setText("15");
}
int newhasNum = Integer.valueOf(col_hasnum.getText().toString());
addMap(dataModel, newhasNum);
}
});
btnreduce.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
initRow();
int hasNum = Integer.valueOf(col_hasnum.getText().toString());
if (hasNum > 0) {
col_hasnum.setText("" + (hasNum - 1));
} else {
col_hasnum.setText("0");
}
int newhasNum = Integer.valueOf(col_hasnum.getText().toString());
addMap(dataModel, newhasNum);
}
});
}
}
上面的viewHolder参数BaseMulViewHolder<TitleModel>和BaseMulViewHolder<DataViewModel>的TitleMoel和DataViewModel如下图:
public class TitleModel extends BaseMulDataModel {
private String title;
private int row;
public TitleModel(){
setType(0);//可以直接在构造方法确定类型
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public TitleModel(String title, int type) {
setType(type);
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
public class DataViewModel extends BaseMulDataModel {
private int hasNum;
private int count;
private String prduceName;
private int col;
private int row;
private String img_url;
private String No;
private int channelId;
public int getChannelId() {
return channelId;
}
public void setChannelId(int channelId) {
this.channelId = channelId;
}
public String getNo() {
return No;
}
public void setNo(String no) {
this.No = no;
}
public String getImg_url() {
return img_url;
}
public void setImg_url(String img_url) {
this.img_url = img_url;
}
public int getCol() {
return col;
}
public void setCol(int col) {
this.col = col;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public DataViewModel(int hasNum, int count, String prduceName, int type) {
setType(type);
this.hasNum = hasNum;
this.count = count;
this.prduceName = prduceName;
}
public int getHasNum() {
return hasNum;
}
public void setHasNum(int hasNum) {
this.hasNum = hasNum;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public String getPrduceName() {
return prduceName;
}
public void setPrduceName(String prduceName) {
this.prduceName = prduceName;
}
}
都是继承自BaseMulDataModel
实现onBindViewHolder实现最后的数据加载
@Override
public void onBindViewHolder(BaseMulViewHolder holder, int position) {
holder.bindData(mList.get(position), position);
}
从而实现了子类属性的分类,最后完成了分类展示。