您的位置:首页 > 移动开发 > Android开发

Android初识RecyclerView 添加分割线、单击事件、长按事件

2017-01-18 16:15 471 查看
一、概述

RecyclerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能。

优点:

RecyclerView封装了viewholder的回收复用

提供了一种插拔式的体验,高度的解耦,异常的灵活

通过布局管理器LayoutManager可以控制其显示的方式

通过ItemDecoration可以控制Item间的间隔(可绘制)

通过ItemAnimator可以控制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'


二、普通列表

1.实现效果图



2.核心代码

列表页面RecyclerViewActivity.java

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<Student> 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<Student>();
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);

}
}


布局文件activity_recyclerview.xml

<?xml version="1.0" encoding="utf-8"?>
<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>


适配器StudentListAdapter.java

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<Student> mList = new ArrayList<Student>();

public StudentListAdapter(Context context) {
this.mContext = context;
}

public void setItems(List<Student> 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);
}
}
}


添加分割线通用工具类ItemDivider.java

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);
}

}


添加单击、长按事件通用工具类RecyclerItemClickListener.java

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) {
}
}


三、网格列表

1.实现效果图



RecyclerView在普通列表和网格列表的切换上面做的比较方便,只需要修改LayoutManager参数即可。

if(flag==1){//普通列表
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}else{//网格列表
mRecyclerView.setLayoutManager(new GridLayoutManager(this,2));
}


四、源代码下载

http://download.csdn.net/detail/chenzheng8975/9740701
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐