前言
RecyclerView自出现后,源自其强大的扩展性,越来越受到欢迎。
它成为了我们日常开发中使用频率最高的控件,所以有必要记录一下他的基础用法。
1.配置build.gradle
想要使用RecyclerView,我们首先要导入support-v7包,所以我们需要在build.gradle中加入如下代码用于自动导入support-v7包。
dependencies {
...
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'
...
}
2.设置布局文件
MainActivity的布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
item的布局文件,这里的布局就只是显示一个文字
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_item"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="moon"
android:gravity="center"/>
</FrameLayout>
3.自定义Adapter
Adapter继承了RecyclerView.Adapter,在onCreateViewHolder中加载条目布局,在onBindViewHolder中将视图与数据进行绑定。
public class HomeAdapter extends RecyclerView.Adapter<MyViewHolder> {
public List<String> mlist;
public Context context;
public OnItemClickListener mClickListener;
public HomeAdapter(Context context,List<String>mlist){
this.context=context;
this.mlist=mlist;
}
public void removeData(int position){
mlist.remove(position);
notifyItemRemoved(position);
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.item_recycler, viewGroup, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(final MyViewHolder myViewHolder, final int i) {
myViewHolder.textView.setText(mlist.get(i));
if (mClickListener!=null){
myViewHolder.textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos =myViewHolder.getLayoutPosition();
mClickListener.onItemClick(myViewHolder.textView,pos);
}
});
myViewHolder.textView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int pos =myViewHolder.getLayoutPosition();
mClickListener.onItemLongClick(myViewHolder.textView,pos);
return false;
}
});
}
}
@Override
public int getItemCount() {
return mlist.size();
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.mClickListener = listener;
}
}
4.自定义ViewHolder
adapter最大的改进就是对ViewHolder进行了封装定义,我们只需要自定义一个ViewHolder继承RecyclerView.ViewHolder就可以了。
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public MyViewHolder(View view) {
super(view);
textView = (TextView) view.findViewById(R.id.tv_item);
}
}
5.设置分割线
在我们的日常使用中,我们会发现默认的RecyclerView是没有分割线的,需要我们自己添加。
设置分割线有很多种方法,比如
1.直接在item.xml文件中在最下方指定一条分割线。
2.添加默认分割线:高度为2px,颜色为灰色
mRecyclerView.addItemDecoration(new RecycleViewDivider(mContext, LinearLayoutManager.VERTICAL));
3.自定义分割线
(最基本的分割线,包括垂直或者水平两个方向,可以设定颜色和高度。)
使用:
垂直方向:CommItemDecoration.createVertical(context, Color.BLUE,30)
水平方向:CommItemDecoration.createHorizontal(context, Color.BLUE,30)
代码如下:
public class CommItemDecoration extends RecyclerView.ItemDecoration {
private static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
private static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private int mSpace = 1; //间隔
private Rect mRect = new Rect(0,0,0,0);
private Paint mPaint = new Paint();
private int mOrientation;
private CommItemDecoration(Context context, int orientation, @ColorInt int color, int space) {
mOrientation = orientation;
if(space>0){
mSpace = space;
}
mPaint.setColor(color);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
public void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mSpace;
mRect.set(left,top,right,bottom);
c.drawRect(mRect,mPaint);
}
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mSpace;
mRect.set(left, top, right, bottom);
c.drawRect(mRect,mPaint);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0,mSpace);
} else {
outRect.set(0, 0, mSpace, 0);
}
}
public static CommItemDecoration createVertical(Context context, @ColorInt int color, int height){
return new CommItemDecoration(context,VERTICAL_LIST,color,height);
}
public static CommItemDecoration createHorizontal(Context context, @ColorInt int color, int width){
return new CommItemDecoration(context,HORIZONTAL_LIST,color,width);
}
}
6.自定义点击事件
我们可以直接在直接在Adapter中的onBindViewHolder()方法中实现点击事件,但是我们也可以自己去定义点击事件
1)首先定义一个接口
我们在这里自定义了条目的点击事件和长按事件
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongClick(View view,int postion);
}
2)再在Adapter中设置回调
public void setOnItemClickListener(OnItemClickListener listener) {
this.mClickListener = listener;
}
3)接下来对item中的控件进行点击事件监听并回调给我们自定义的监听
@Override
public void onBindViewHolder(final MyViewHolder myViewHolder, final int i) {
myViewHolder.textView.setText(mlist.get(i));
if (mClickListener!=null){
myViewHolder.textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos =myViewHolder.getLayoutPosition();
mClickListener.onItemClick(myViewHolder.textView,pos);
}
});
myViewHolder.textView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int pos =myViewHolder.getLayoutPosition();
mClickListener.onItemLongClick(myViewHolder.textView,pos);
return false;
}
});
}
}
4)最后在Activity中进行监听
homeAdapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(View view, final int position) {
int i=position+1;
Toast.makeText(MainActivity.this, "item "+i, Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View view, final int postion) {
int i=postion+1;
new AlertDialog.Builder(MainActivity.this)
.setTitle("确认删除 item "+i+"?")
.setNegativeButton("取消",null)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
homeAdapter.removeData(postion);
}
}).show();
}
});
7.实现效果
1)点击效果
2)长按效果
长按时会弹出对话框,删除时会有消失动画
8.实现GirdView
我们也可以使用RecyclerView来实现GirdView,只需要自定义横向的分割线,在MainActivity中设置:
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.VERTICAL));
recyclerView.addItemDecoration(CommItemDecoration.createHorizontal(this,Color.GREEN,2));
效果图:
最后
通过学习和整理出RecyclerView的基本使用后感觉对RecyclerView更多的感触,之前只知道对着书或者视频照着葫芦画瓢,现在也是对这一个常用的控件有了一定的了解,但是肯定还是存在很多漏洞,在以后的学习如果有了其他想法或者发现错误,会回来继续更正。