从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,可以用来代替传统的ListView,更加强大和灵活。RecyclerView的官方定义如下:
RecyclerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能。
在build.gradle文件中引入该类:
compile 'com.android.support:recycleview-v7:25.0.1'
private RecyclerView mRecyclerView;
private RecyclerAdapter mAdapter;
LinearLayoutManager layoutManager = new LinearLayoutManager(this );
layoutManager.setOrientation(OrientationHelper.VERTICAL); //设置为垂直布局,这也是默认的
mRecyclerView.setLayoutManager(layoutManager);//设置布局管理器
mAdapter = new RecyclerAdapter(this, dataBeanList);//创建适配器
mRecyclerView.setAdapter(mAdapter);//设置Adapter
mRecyclerView.setItemAnimator();//设置增加或删除条目的动画
mRecyclerView.addItemDecoration();//设置分隔线
//滚动监听
mAdapter.setOnScrollListener(new RecyclerAdapter.OnScrollListener() {
@Override
public void scrollTo(int pos) {
mRecyclerView.scrollToPosition(pos);
}
});
标准实现步骤如下:
① 创建Adapter:创建一个继承RecyclerView.Adapter
的Adapter类(VH是ViewHolder的类名)
② 创建ViewHolder:在Adapter中创建一个继承RecyclerView.ViewHolder
的静态内部类,记为VH。
ViewHolder的实现和ListView的ViewHolder实现几乎一样。
③ 在Adapter中实现4个方法:
1.onCreateViewHolder()
这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。
需要注意的是在onCreateViewHolder()
中,映射Layout必须为
view = mInflater.inflate(R.layout.recycleview_item_parent, parent, false);
不能为:view = mInflater.inflate(R.layout.recycleview_item_parent, null);
2.onBindViewHolder()
这个方法主要用于适配渲染数据到View中。方法提供给你viewHolder而不是原来的convertView。
3.getItemCount()
这个方法就类似于BaseAdapter的getCount方法了,即总共有多少个条目。
4.getItemViewType(int position)
这个方法不是必须实现,前三种必须实现,此方法作用可以根据需求自定义类型在onCreateViewHolder和onBindViewHolder做相应处理。如BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType),viewtype即是getItemViewType方法的返回值,onBindViewHolder(BaseViewHolder holder, int position)这个方法可以通过getItemViewType(position)的得到类型并作相应处理。
可以看出,RecyclerView将ListView中getView()
的功能拆分成了onCreateViewHolder()
和onBindViewHolder()
。
public class RecyclerAdapter extends RecyclerView.Adapter{
private Context context;
private List dataBeanList;
private LayoutInflater mInflater;
private OnScrollListener mOnScrollListener;
public RecyclerAdapter(Context context, List dataBeanList) {
this.context = context;
this.dataBeanList = dataBeanList;
this.mInflater = LayoutInflater.from(context);
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = null;
switch (viewType) {
case DataBean.PARENT_ITEM:
view = mInflater.inflate(R.layout.recycleview_item_parent, parent, false);
return new ParentViewHolder(context, view);
case DataBean.CHILD_ITEM:
view = mInflater.inflate(R.layout.recycleview_item_child, parent, false);
return new ChildViewHolder(context, view);
default:
view = mInflater.inflate(R.layout.recycleview_item_parent, parent, false);
return new ParentViewHolder(context, view);
}
}
/**
* 根据不同的类型绑定View
*
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
switch (getItemViewType(position)) {
case DataBean.PARENT_ITEM:
ParentViewHolder parentViewHolder = (ParentViewHolder) holder;
parentViewHolder.bindView(dataBeanList.get(position), position, itemClickListener);
break;
case DataBean.CHILD_ITEM:
ChildViewHolder childViewHolder = (ChildViewHolder) holder;
childViewHolder.bindView(dataBeanList.get(position), position);
break;
}
}
@Override
public int getItemCount() {
return dataBeanList.size();
}
@Override
public int getItemViewType(int position) {
return dataBeanList.get(position).getType();
}
private ItemClickListener itemClickListener = new ItemClickListener() {
@Override
public void onExpandChildren(DataBean bean) {
int position = getCurrentPosition(bean.getID());//确定当前点击的item位置
DataBean children = getChildDataBean(bean);//获取要展示的子布局数据对象,注意区分onHideChildren方法中的getChildBean()。
if (children == null) {
return;
}
add(children, position + 1);//在当前的item下方插入
if (position == dataBeanList.size() - 2 && mOnScrollListener != null) { //如果点击的item为最后一个
mOnScrollListener.scrollTo(position + 1);//向下滚动,使子布局能够完全展示
}
}
@Override
public void onHideChildren(DataBean bean) {
int position = getCurrentPosition(bean.getID());//确定当前点击的item位置
DataBean children = bean.getChildBean();//获取子布局对象
if (children == null) {
return;
}
remove(position + 1);//删除
if (mOnScrollListener != null) {
mOnScrollListener.scrollTo(position);
}
}
};
/**
* 在父布局下方插入一条数据
*
* @param bean
* @param position
*/
public void add(DataBean bean, int position) {
dataBeanList.add(position, bean);
notifyItemInserted(position);
}
/**
* 移除子布局数据
*
* @param position
*/
protected void remove(int position) {
dataBeanList.remove(position);
notifyItemRemoved(position);
}
/**
* 确定当前点击的item位置并返回
*
* @param uuid
* @return
*/
protected int getCurrentPosition(String uuid) {
for (int i = 0; i < dataBeanList.size(); i++) {
if (uuid.equalsIgnoreCase(dataBeanList.get(i).getID())) {
return i;
}
}
return -1;
}
/**
* 封装子布局数据对象并返回
* 注意,此处只是重新封装一个DataBean对象,为了标注Type为子布局数据,进而展开,展示数据
* 要和onHideChildren方法里的getChildBean()区分开来
*
* @param bean
* @return
*/
private DataBean getChildDataBean(DataBean bean) {
DataBean child = new DataBean();
child.setType(1);
child.setParentLeftTxt(bean.getParentLeftTxt());
child.setChildLeftTxt(bean.getChildLeftTxt());
child.setChildRightTxt(bean.getChildRightTxt());
child.setListdata(bean.getListdata());
return child;
}
/**
* 滚动监听接口
*/
public interface OnScrollListener {
void scrollTo(int pos);
}
public void setOnScrollListener(OnScrollListener onScrollListener) {
this.mOnScrollListener = onScrollListener;
}
}
public class BaseViewHolder extends RecyclerView.ViewHolder {
public BaseViewHolder(View itemView) {
super(itemView);
}