- 参考:
这是一篇Android RecyclerView使用介绍哦(好!) - 本文的源代码:
RecyclerViews
一. RecyclerView的基础用法
- 添加依赖
compile 'com.android.support:recyclerview-v7:25.2.0'
- xml使用布局
- 新建recycler_item的布局(recyclerview中的item的布局,此处的布局是CardView嵌套了ImageView)
- 新建Adapter
public class LinearRecyclerAdapter extends RecyclerView.Adapter {
private Context mContext;
private List mMeiziList;
/*构造函数,进行初始化(一般传入context和数据列表)*/
public LinearRecyclerAdapter(Context context,List meiziList) {
mContext = context;
mMeiziList = meiziList;
}
/*创建ViewHolder*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.recycler_item_linear_recycler,parent,false);
return new ViewHolder(view);
}
/*数据绑定到ViewHolder*/
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Meizi meizi = mMeiziList.get(position);
Picasso.with(mContext).load(meizi.getImageUrl()).into(holder.mImageView);
}
/*item的数量,一般就是数据List的大小*/
@Override
public int getItemCount() {
return mMeiziList.size();
}
/*内部类ViewHolder*/
class ViewHolder extends RecyclerView.ViewHolder {
private ImageView mImageView;
ViewHolder(View itemView) {
super(itemView);
mImageView = (ImageView) itemView.findViewById(R.id.iv_meizi);
}
}
/*添加item的函数*/
public void addItem(Meizi meizi, int position) {
mMeiziList.add(position, meizi);
notifyItemInserted(position);
}
/*滑动删除会调用的函数*/
public void removeItem(final int position) {
final Meizi removed=mMeiziList.get(position);
mMeiziList.remove(position);
notifyItemRemoved(position);
Toast.makeText(mContext,"你删除了第"+position+"个item",Toast.LENGTH_SHORT).show();
}
}
- 实例化RecyclerView,设置布局管理器和Adapter
mRecyclerView = (RecyclerView) mRootView.findViewById(R.id.recycler_view_linear);//初始化recyclerview
mLayoutManager = new LinearLayoutManager(getContext());//初始化布局管理器
mRecyclerView.setLayoutManager(mLayoutManager);//设置布局管理器
- 获取数据,封装到List中,实例化Adapter,给RecyclerView设置Adapter
二. 下拉刷新的实现
- 实例化SwipeRefreshLayout
/*初始化下拉刷新控件*/
mSwipeRefreshLayout = (SwipeRefreshLayout) mRootView.findViewById(R.id.swipe_refresh_linear_recycler);
- 下拉刷新监听
/*swipeRefreshLayout刷新监听*/
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
//下拉刷新之后要进行的操作,一般是重新加载数据
new GetMeiziTask().execute("http://gank.io/api/data/福利/10/1 ");
}
});
- 刷新之后记得调用
mSwipeRefreshLayout.setRefreshing(false);
取消显示刷新的按钮,每次在刷新之前可以调用mSwipeRefreshLayout.setRefreshing(true);
显示刷新按钮(一般在AsyncTask的onPreExecute中)
三. 滑动删除和长按交换位置的实现
- 原理
- 滑动删除就是监听滑动事件,然后在回调方法中,将数据list中的对应元素删除
- 长按交换位置就是长按事件,然后在回调方法中,将数据list中的对应元素进行移动
- 使用方法
- 实例化ItemTouchHelper类,在回调方法中实现滑动删除
/*item触摸助手类,用于实现滑动删除等操作*/
mItemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
//用于设置拖拽和滑动的方向
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags=0,swipeFlags=0;
if(recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager ||recyclerView.getLayoutManager() instanceof GridLayoutManager){
//网格式布局有4个方向
dragFlags=ItemTouchHelper.UP|ItemTouchHelper.DOWN|ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT;
}else if(recyclerView.getLayoutManager() instanceof LinearLayoutManager){
//线性式布局有2个方向
dragFlags=ItemTouchHelper.UP|ItemTouchHelper.DOWN;
swipeFlags = ItemTouchHelper.START|ItemTouchHelper.END; //设置侧滑方向为从两个方向都可以
}
return makeMovementFlags(dragFlags,swipeFlags);//swipeFlags 为0的话item不滑动
}
//长摁item拖拽时会回调这个方法
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
/*int from=viewHolder.getAdapterPosition();
int to=target.getAdapterPosition();
Meizi moveItem=mMeiziList.get(from);
mMeiziList.remove(from);
mMeiziList.add(to,moveItem);//交换数据链表中数据的位置
mLinearRecyclerAdapter.notifyItemMoved(from,to);//更新适配器中item的位置*/
int from=viewHolder.getAdapterPosition();
int to=target.getAdapterPosition();
Collections.swap(mMeiziList,from,to);
mLinearRecyclerAdapter.notifyItemMoved(from,to);
return true;
}
/*滑动删除*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
mLinearRecyclerAdapter.removeItem(viewHolder.getAdapterPosition());
}
});
- 将ItemTouchHelper与RecyclerView绑定
mItemTouchHelper.attachToRecyclerView(mRecyclerView);//触摸事件关联到RecyclerView
四. 简单的RecyclerItem动画的实现
/*设置item加载或移除时的动画*/
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
五. item的点击事件实现
- 在Adapter里面实现事件监听
- 在ViewHolder里直接给控件添加监听事件
ViewHolder(View itemView) {
super(itemView);
mImageView = (ImageView) itemView.findViewById(R.id.iv_meizi);
mImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext,"You clicked item "+getAdapterPosition(),Toast.LENGTH_SHORT).show();
}
});
}
- 在onBindViewHolder方法里给控件添加监听事件
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
Meizi meizi = mMeiziList.get(position);
Picasso.with(mContext).load(meizi.getImageUrl()).into(holder.mImageView);
/*holder.mImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext,"You clicked item "+holder.getAdapterPosition(),Toast.LENGTH_SHORT).show();
}
});*/
}
- 在调用的地方实现回调的监听和处理
- Adapter实现回掉接口,在调用处进行调用
六. 上拉加载
- 上拉加载就是先设置onScrollListener,在listener方法里面进行判断然后加载数据,加载数据的原理是获取新的数据然后添加到List集合中,然后再调用Adapter的notifyDataSetChanged通知更新数据。
七. 四大角色
- RecyclerView
RecyclerView就是一个控件,和普通控件一样,只不过他的作用是用来展示列表,回收和定位屏幕上的view
- Adapter
适配器,用来创建RecyclerView的界面(ViewHolder),加载数据到界面上,当RecyclerView需要显示view时,就会去找它的adapter。具体过程如下:
- 调用adapter的getIemCount()方法,询问列表对象的总个数
- 调用adapter的createViewHolder()方法,创建ViewHolder和要显示的视图
- 传入ViewHolder和要加载的视图位置,调用adapter的onBindViewHolder()方法,为视图绑定数据
每当需要加载一个item的时候就会调用以上方法,直到需要加载的item都加载完成
- LayoutManager
用来定义RecyclerView的显示规则(如定位列表项,定义屏幕的滚动行为等),正因为有LayoutManager的存在,才使得RecyclerView显示变得更灵活
- ViewHolder
ViewHolder在这里用来容纳每个item里面的控件引用,然后执行findViewById方法。因为recyclerView里面的每个item都有相同的控件引用,所以使用ViewHolder之后就可以减少findViewById方法的调用从而提高性能。