Hellow小伙伴们,好久没更新了,最近忙死了,最近在做项目的时候要用到Recyclerview,并且要监听它的滑动,这时就上网查了一下,我滴乖乖,好老的博客,不过能用,但是在学他们使用的时候发现了一个致命的问题,你只要动一下就能监测到你的变化。或许这里表述不清楚,那么我们直接看具体案列。
这里可能需要花费你很多时间阅读,但是弄清楚了对你是个巨大的飞跃并且,我只做了对上下滑动的监听,弄懂如下代码之后就可以实现对左右左上,左下等方向的监听了.
实现方法一(最原始的):
ReyclerView中有个ScrollListener这个监听
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if(newState == 0)
{
//表示屏幕已停止。屏幕停止滚动时为
}else if(newState == 1){
//表示正在滚动。当屏幕滚动且用户使用的触碰或手指还在屏幕上时为
}else if(newState == 2){
//表示手指做了抛的动作(手指离开屏幕前,用力滑了一下,屏幕产生惯性滑动)。
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if(dy>0){
//向上滑动
}
else{
//向下滑动
}
}
});
这个是可以实现我们的上下左右滑动的监听的,但是致命问题也就在这,当你一直往下或者上滑动的时候,这个方法将一直被触发。问题就在这,可能你要在当recyclerView向下滑动的额时候你要做某些操作,这时候你持续往下滑这个方法将会倍执行N次,这不是我们想要的。
所以这个时候,我们想要的是向下滑动的时候就触发一次,向上滑动的时候就触发一次。这个该怎么来实现嫩。学过数据库的人应该很容易联想到我们的锁的概念,当执行某个事物的时候其他事件不能去抢占执行他。
所以我们有了一个大体的思路。
1.当手指向上滑动的时候,触发一次向上滑动,锁定它,不再触发。即使手指还在向上滑动
2.当手指向下滑动的时候,触发一次向下滑动,锁定它,不再触发。即使手指还在向下滑动
3.当手指滑动方向发生改变的时候,释放我们的锁.
这么一来不就可以实现了么?
下面是我封装的一个可以拓展的RecyclerViewHelper,简单的实现了想要实现的逻辑,拓展非常容易(囊括了接口回调,不动的我的博客有详解,以及我们的Builder设计模式,还有实现多接口实现其中的某个方法)
/**
* Created by meng on 2018/2/9.
*/
public class RecyclerHelper extends RecyclerView.OnScrollListener {
private mScrollListener mListener;
private RecyclerView recyclerView;
private boolean LOCK_Y;//锁住Y方向的滑动
private boolean LOCK_X;//锁住X方向的滑动
private float OLD_DY = -1;//临时存放dy
private float OLD_DX = -1;//临时存放dx
/**
* 采用Builder模式来构建
*/
private RecyclerHelper(){
}
private RecyclerHelper(RecyclerHelper recyclerHelper){
this.recyclerView=recyclerHelper.recyclerView;
}
public void setLostener(mScrollListener lostener){
this.mListener = lostener;
}
public void Listener(){
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if(mListener!=null){
if(newState == 0)
mListener.SCROLL_STATE_IDLE();//表示屏幕已停止。屏幕停止滚动时为
else if(newState == 1)
mListener.SCROLL_STATE_TOUCH_SCROLL();//表示正在滚动。当屏幕滚动且用户使用的触碰或手指还在屏幕上时为1
else if(newState == 2)
mListener.SCROLL_STATE_FLING();//表示手指做了抛的动作(手指离开屏幕前,用力滑了一下,屏幕产生惯性滑动)。
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if(mListener !=null){
if((OLD_DY <0&&dy>0) ||(OLD_DY>0&&dy<0))
{
LOCK_Y = false;//当运动方向发生改变的时候解除对Y轴的锁定
}
if(dy > 0)
{
if(!LOCK_Y)
{
LOCK_Y = true;//手指向上滑动并且要锁住Y轴,防止多彩回调
mListener.upGlide();
}
}
else if(dy < 0 )
{
if(!LOCK_Y)
{
LOCK_Y = true;//同上
mListener.downGlide();
}
}
OLD_DY = dy;//记录旧的DY
}//end if
}//end
});//end onScrolled
}
public static class Builder{
private RecyclerHelper target;
public Builder(){
target = new RecyclerHelper();
}
public Builder addRecyclerView(RecyclerView recyclerView){
target.recyclerView = recyclerView;
return this;
}
public Builder addSetScroListener(mScrollListener listener){
target.mListener = listener;
return this;
}
public RecyclerHelper build() {
return new RecyclerHelper(target);
}
}
public interface mScrollListener{
void upGlide();//手指向上滑动,并且脱离手机
void downGlide();//手指向下滑动,并且脱离了手机
void leftGlide();//手指向左滑动
void rightGlide();//手指向右滑动
void upAndrightGlide();//手指右上滑动
void upAndleftGlide();//手指向左上滑动
void downAndrightGlide();//手指向右下滑动
void downAndleftGlide();//手指向左下滑动
void SCROLL_STATE_FLING();//屏幕处于甩动状态
void SCROLL_STATE_IDLE();//停止滑动状态
void SCROLL_STATE_TOUCH_SCROLL();// 手指接触状态
}
public static class mScrollListenerImpl implements mScrollListener {
@Override
public void upGlide() {
}
@Override
public void downGlide() {
}
@Override
public void leftGlide() {
}
@Override
public void rightGlide() {
}
@Override
public void upAndrightGlide() {
}
@Override
public void upAndleftGlide() {
}
@Override
public void downAndrightGlide() {
}
@Override
public void downAndleftGlide() {
}
@Override
public void SCROLL_STATE_FLING() {
}
@Override
public void SCROLL_STATE_IDLE() {
}
@Override
public void SCROLL_STATE_TOUCH_SCROLL() {
}
}
}
使用方法1:
RecyclerHelper recyclerHelper = new RecyclerHelper.Builder()
.addRecyclerView(recyclerView)
.build();
recyclerHelper.setLostener(new RecyclerHelper.mScrollListenerImpl(){
@Override
public void upGlide() {
super.upGlide();
}
@Override
public void downGlide() {
super.downGlide();
}
});
使用我们做项目的时候经常用到的Bulider模式,支持相当容易的扩展.
这里还有一处特别重要的地方为社么这么我们new 的是 mScrollListenerImpl(),而不是mScrollListener(),这就是一个技巧性地问题了,我们平时写一些代码的时候经常会碰到,回调接口过多,但是只想实现其中的一些方法,这个情况下用上述的技巧可以减轻代码量,看着个舒服了.
使用方法2:直接implements我们的接口就好了.
支持原创,转载的时候注明转载出处,谢谢。