一、概述
RecyclerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能。
优点:
缺点:
RecyclerView.Adapter需要实现3个方法:
1.onCreateViewHolder()
这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。直接省去了当初的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。
2.onBindViewHolder()
这个方法主要用于适配渲染数据到View中。方法提供给你了一个viewHolder,而不是原来的convertView。
3.getItemCount()
这个方法就类似于BaseAdapter的getCount方法了,即总共有多少个条目。
在项目使用需要添加依赖:
compile 'com.android.support:recyclerview-v7:24.2.1'
二、普通列表
2.核心代码
package com.czhappy.recyclerviewdemo.activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Toast;
import com.czhappy.recyclerviewdemo.R;
import com.czhappy.recyclerviewdemo.adapter.StudentListAdapter;
import com.czhappy.recyclerviewdemo.listener.RecyclerItemClickListener;
import com.czhappy.recyclerviewdemo.model.Student;
import com.czhappy.recyclerviewdemo.view.ItemDivider;
import java.util.ArrayList;
import java.util.List;
import static com.czhappy.recyclerviewdemo.R.id.recyclerView;
/**
* Description:
* User: chenzheng
* Date: 2017/1/18 0018
* Time: 10:42
*/
public class RecyclerViewActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private List list;
private StudentListAdapter adapter;
private int flag = 1;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recyclerview);
flag = getIntent().getIntExtra("flag", 1);
initData();
initView();
}
private void initData() {
list = new ArrayList();
for (int i = 0; i < 20; i++) {
Student s = new Student();
s.setUserName("我是学生"+i);
list.add(s);
}
}
private void initView() {
mRecyclerView = (RecyclerView) this.findViewById(recyclerView);
//设置布局管理器
if(flag==1){//普通列表
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}else{//网格列表
mRecyclerView.setLayoutManager(new GridLayoutManager(this,2));
}
//设置adapter
adapter = new StudentListAdapter(this);
mRecyclerView.setAdapter(adapter);
//设置Item增加、移除动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//添加分割线
mRecyclerView.addItemDecoration(new ItemDivider().setDividerWith(1).setDividerColor(0xffdddddd));
mRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener(this, mRecyclerView, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(RecyclerViewActivity.this, "单击:position="+position, Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View view, int position) {
Toast.makeText(RecyclerViewActivity.this, "长按:position="+position, Toast.LENGTH_SHORT).show();
}
}));
//添加数据
adapter.setItems(list);
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"/>
LinearLayout>
package com.czhappy.recyclerviewdemo.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.czhappy.recyclerviewdemo.R;
import com.czhappy.recyclerviewdemo.model.Student;
import java.util.ArrayList;
import java.util.List;
/**
* Description:
* User: chenzheng
* Date: 2017/1/18 0018
* Time: 11:06
*/
public class StudentListAdapter extends RecyclerView.Adapter<StudentListAdapter.StudentViewHolder> {
private Context mContext;
private List mList = new ArrayList();
public StudentListAdapter(Context context) {
this.mContext = context;
}
public void setItems(List list) {
this.mList = list;
notifyDataSetChanged();
}
@Override
public StudentListAdapter.StudentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
StudentViewHolder viewHolder = new StudentViewHolder(LayoutInflater.from(mContext)
.inflate(R.layout.item_student_list, parent, false));
return viewHolder;
}
@Override
public void onBindViewHolder(StudentListAdapter.StudentViewHolder holder, int position) {
if(mList!=null && mList.size()>0){
Student student = mList.get(position);
holder.name_tv.setText(student.getUserName());
}
}
@Override
public int getItemCount() {
return mList!=null ? mList.size() : 0;
}
class StudentViewHolder extends RecyclerView.ViewHolder {
private TextView name_tv;
public StudentViewHolder(View itemView) {
super(itemView);
name_tv = (TextView) itemView.findViewById(R.id.name_tv);
}
}
}
package com.czhappy.recyclerviewdemo.view;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
/**
* Description:
* User: chenzheng
* Date: 2017/1/18 0018
* Time: 13:54
*/
public class ItemDivider extends RecyclerView.ItemDecoration {
private int dividerWith = 1;
private Paint paint;
private RecyclerView.LayoutManager layoutManager;
// 构造方法,可以在这里做一些初始化,比如指定画笔颜色什么的
public ItemDivider() {
initPaint();
paint.setColor(0xffff0000);
}
private void initPaint() {
if (paint == null) {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
}
}
public ItemDivider setDividerWith(int dividerWith) {
this.dividerWith = dividerWith;
return this;
}
public ItemDivider setDividerColor(int color) {
initPaint();
paint.setColor(color);
return this;
}
/**
* 指定item之间的间距(就是指定分割线的宽度) 回调顺序 1
* @param outRect Rect to receive the output.
* @param view The child view to decorate
* @param parent RecyclerView this ItemDecoration is decorating
* @param state The current state of RecyclerView.
*/
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
if (layoutManager == null) {
layoutManager = parent.getLayoutManager();
}
// 适用 LinearLayoutManager 和 GridLayoutManager
if (layoutManager instanceof LinearLayoutManager) {
int orientation = ((LinearLayoutManager) layoutManager).getOrientation();
if (orientation == LinearLayoutManager.VERTICAL) {
// 水平分割线将绘制在item底部
outRect.bottom = dividerWith;
} else if (orientation == LinearLayoutManager.HORIZONTAL) {
// 垂直分割线将绘制在item右侧
outRect.right = dividerWith;
}
if (layoutManager instanceof GridLayoutManager) {
GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams) view.getLayoutParams();
// 如果是 GridLayoutManager 则需要绘制另一个方向上的分割线
if (orientation == LinearLayoutManager.VERTICAL && lp != null && lp.getSpanIndex() > 0) {
// 如果列表是垂直方向,则最左边的一列略过
outRect.left = dividerWith;
} else if (orientation == LinearLayoutManager.HORIZONTAL && lp != null && lp.getSpanIndex() > 0) {
// 如果列表是水平方向,则最上边的一列略过
outRect.top = dividerWith;
}
}
}
}
/**
* 在item 绘制之前调用(就是绘制在 item 的底层) 回调顺序 2
* 一般分割线在这里绘制
* 看到canvas,对自定义控件有一定了解的话,就能想到为什么说给RecyclerView设置分割线更灵活了
* @param c Canvas to draw into
* @param parent RecyclerView this ItemDecoration is drawing into
* @param state The current state of RecyclerView
*/
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
// 这个值是为了补偿横竖方向上分割线交叉处间隙
int offSet = (int) Math.ceil(dividerWith * 1f / 2);
for (int i = 0; i < parent.getChildCount(); i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int left1 = child.getRight() + params.rightMargin;
int right1 = left1 + dividerWith;
int top1 = child.getTop() - offSet - params.topMargin;
int bottom1 = child.getBottom() + offSet + params.bottomMargin;
//绘制分割线(矩形)
c.drawRect(left1, top1, right1, bottom1, paint);
int left2 = child.getLeft() - offSet - params.leftMargin;
int right2 = child.getRight() + offSet + params.rightMargin;
int top2 = child.getBottom() + params.bottomMargin;
int bottom2 = top2 + dividerWith;
//绘制分割线(矩形)
c.drawRect(left2, top2, right2, bottom2, paint);
}
}
/**
* 在item 绘制之后调用(就是绘制在 item 的上层) 回调顺序 3
* 也可以在这里绘制分割线,和上面的方法 二选一
* @param c Canvas to draw into
* @param parent RecyclerView this ItemDecoration is drawing into
* @param state The current state of RecyclerView
*/
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
}
package com.czhappy.recyclerviewdemo.listener;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
/**
* Description:
* User: chenzheng
* Date: 2017/1/18 0018
* Time: 14:27
*/
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
}
private OnItemClickListener mListener;
private GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null) {
mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
三、网格列表
RecyclerView在普通列表和网格列表的切换上面做的比较方便,只需要修改LayoutManager参数即可。
if(flag==1){//普通列表
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}else{//网格列表
mRecyclerView.setLayoutManager(new GridLayoutManager(this,2));
}
四、源代码下载
http://download.csdn.net/detail/chenzheng8975/9740701