您的位置:首页 > 其它

RecyclerView进阶(二)点击事件的实现

2017-04-10 23:32 127 查看
个人总结、笔记之用,如有错误欢迎指正。

先列出来LayoutManager的常用方法:

findFirstVisibleItemPosition()
返回当前第一个可见 Item 的 position

findFirstCompletelyVisibleItemPosition()
返回当前第一个完全可见 Item 的 position

findLastVisibleItemPosition()
返回当前最后一个可见 Item 的 position

findLastCompletelyVisibleItemPosition()
返回当前最后一个完全可见 Item 的 position.

scrollBy()
滚动到某个位置。

一、模仿ListView实现

RecyclerView并没有提供ListView中常用的OnItemClickListener。所以需要我们来自定义一个相应的接口,Adapter就是一个很好的地方。

1.定义接口

/**
* 自定义点击接口
*/
public static interface onRecyclerItemClickListener{
/**
* item view回调方法
* @param view 被点击的view
* @param position 点击索引
*/
void onItemClick(View view,int position);
void onLongItemClick(View view, int position);
}


2.添加接口和初始化方法

//初始化
private onRecyclerItemClickListener mOnRecyclerItemClickListener = null;

//初始化方法
public void setOnRecyclerItemClickListener(onRecyclerItemClickListener onRecyclerItemClickListener) {
mOnRecyclerItemClickListener = onRecyclerItemClickListener;
}


3.在初始化时候添加点击事件

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener{
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
ViewHolder vh = new ViewHolder(view);
//将创建的View注册点击事件
view.setOnClickListener(this);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int i) {
viewHolder.mTextView.setText(datas.get(i).title);
//将数据保存在itemView的Tag中,以便点击时进行获取
viewHolder.itemView.setTag(position);
}
...
//将点击事件转移给外面的调用者
@Override
public void onClick(View v) {
if (mOnItemClickListener != null) {
//注意这里使用getTag方法获取数据
mOnItemClickListener.onItemClick(v,v.getTag());
}
}
...
}


4.在Activity中调用

mAdapter.setOnRecyclerItemClickListener(new MyAdapter.onRecyclerItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(RecyclerViewActivity.this, "点击事件", Toast.LENGTH_LONG).show();
}
});


这种方式实现起来比较简单,但是显而易见,对性能是不友好的。

二、OnItemTouchListener实现

官方提供了一个OnItemTouchListener接口,用来处理相应的触摸事件。并且提供了一个实现类SimpleOnItemTouchListener,这是一个有空方法体和默认返回值的实现类。

You may prefer to extend this class if you don’t need to override all methods. Another benefit of using this class is future compatibility. As the interface may change, we’ll always provide a default implementation on this class so that your code won’t break when you update to a new version of the support library.

继承这个类可以很方便的实现简单的点击事件。先来看看这个类

public static class SimpleOnItemTouchListener implements RecyclerView.OnItemTouchListener {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
return false;
}

@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}

@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}


只有简单的三个方法。第一个是处理触摸事件的,第二个是拦截触摸事件的,第三个是处理触摸冲突的。

实际上,实现OnItemTouchListener必须实现的也就是这三个方法。

OnTouchEvent()
中,当触摸时会回调一个MotionEvent对象,我们通过使用
GestureDetectorCompat
来解析用户的操作.

这里我们选择通过实现OnItemTouchListener来实现点击监听。

public abstract class OnRecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private RecyclerView mRecyclerView;
private GestureDetectorCompat mGestureDetector;

public OnRecyclerItemClickListener(RecyclerView recyclerView) {
this.mRecyclerView = recyclerView;
this.mGestureDetector = new GestureDetectorCompat(mRecyclerView.getContext(),new MyGestureListener());
}

public abstract  void onItemClick(View view, int position);
public abstract void onLongItemClick(View view, int position);

@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
return false;
}

@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
}

@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

}

private class MyGestureListener extends GestureDetector.SimpleOnGestureListener{
/**
* 单击抬起回调
*/
@Override
public boolean onSingleTapUp(MotionEvent e) {
View child = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null) {
//RecyclerView.ViewHolder viewHolder = mRecyclerView.getChildViewHolder(child);
onItemClick(child,mRecyclerView.getChildAdapterPosition(child));
}
return true;
}

/**
* @param e
*/
@Override
public void onLongPress(MotionEvent e) {
View child = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null) {
// RecyclerView.ViewHolder viewHolder = mRecyclerView.getChildViewHolder(child);
onLongItemClick(child,mRecyclerView.getChildAdapterPosition(child));
}
}
}
}


在GestureDetectorCompat的手势回调中我们覆写:

boolean onSingleTapUp(MotionEvent e)单击抬起回调

void onLongPress(MotionEvent e)长按回调

在RecyclerView的对象中添加
addOnItemTouchListener()
方法,然后在回调中处理你需要的事件

mRecyclerView.addOnItemTouchListener(new OnRecyclerItemClickListener(mRecyclerView) {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(RecyclerViewActivity.this,"点击事件",Toast.LENGTH_SHORT).show();
}

@Override
public void onLongItemClick(View view, int position) {
Toast.makeText(RecyclerViewActivity.this,"长按事件",Toast.LENGTH_SHORT).show();
}
});
}


参考:http://blog.devwiki.net/index.php/2016/07/24/three-ways-click-recyclerview-item.html

参考:https://segmentfault.com/a/1190000005176416
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: