Android开发:解决RecyclerView无法使用缩放类ScaleGestureDetector的问题

       (欢迎转载,但转载请注明出处:https://blog.csdn.net/actionwind/article/details/112651614,引用请注明章节。)

       根据Android官方的API文档,使用ScaleGestureDetector和它OnScaleGestureListener对View用手势进行缩放的时候是这么做的:ScaleGestureDetector(Context context, ScaleGestureDetector.OnScaleGestureListener listener)……………………。详细的方法网上已经有很多,在这里我就不多说了。但这几天我在写程序的时候发现如果要对RecyclerView进行缩放的话,用一般对付View的方法使用ScaleGestureDetector是不行的,它的监听器无法获取到手指缩放的动作,因为手势的输入都被RecyclerView给拦截了,RecyclerView它自己要对手势进行处理,一般是滑动操作,但它自己又不支持手势缩放动作的处理,所以ScaleGestureDetector对View的一般使用方法无法用在RecyclerView上。

       然后在网上搜来搜去,看了几个解决方案大致都是自己创建类和方法去监听和处理缩放的手势(佩服佩服,五体投地),实在是太麻烦了,总觉得Android官方不会给RecyclerView留一个这么大的缺陷交给Android  app开发者去解决。于是结合网上各位大牛的解决方案再去多看了几眼Android的API文档,最终找到了简单一些的解决方案,网上好像找不到这样的方法,所以在这里做一下记录吧。

   (欢迎转载,但转载请注明出处:https://blog.csdn.net/actionwind/article/details/112651614,引用请注明章节。)

       简单地说,RecyclerView提供了一个内部类OnItemTouchListener,这个监听器的作用是:当在RecyclerView上的点触手势操作被RecyclerView强制“抢走”之前,你可以对它们进行拦截,转送给其他方法进行处理。有了这个监听器我们就可以将缩放手势操作抽离出来,交给ScaleGestureDetector的监听器去处理了,具体做法如下:      

//创建一个类同时实现RecyclerView的OnItemTouchListener接口和ScaleGestureDetector的OnScaleGestureListener接口
class PdfScale implements RecyclerView.OnItemTouchListener, ScaleGestureDetector.OnScaleGestureListener {
    RecyclerView recView;
    ScaleGestureDetector scaleDetector;
    float scaleBase=1;
    float scaleLevel=1;
    float average=1;
    float scaledRecord=0;

    @Override
    public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {//这个方法用于判断点触手势要不要被拦截,要拦截的话就会把手势送给下面的onTouchEvent去处理。
        recView = rv;//获取外面传过来的要进行缩放的RecyclerView
        scaleDetector = new ScaleGestureDetector(rv.getContext(), this);//初始化ScaleGestureDetector对象,让它绑定我们要进行缩放处理的rv,指定监听器用本身这个OnScaleGestureListener

        if (e.getPointerCount() > 1) {//缩放的手势起码要两根手指来完成吧?所以检测到RecyclerView上的触点大于1的时候,return true就是把这类手势转送给onTouchEvent去处理。
            return true;
        } else {//其他操作则不拦截,仍由RecyclerView自身去处理。
            return false;
        }
    }

    @Override
    public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {//这个是转发手势的接口,这次我们在这里要做的就简单了,
        scaleDetector.onTouchEvent(e);//直接把手势交给ScaleGestureDetector去处理。
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {//这个方法我们这次不需要用到,但是OnItemTouchListener要求必须实现它,留空即可。

    }

//以下几个方法都是OnScaleGestureListener接口要求必须实现的。寻寻觅觅找到这篇文章的同学,应该早就知道下面几个的实现方法,我也就不说得太详细了:
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        average=(average+detector.getCurrentSpan())/2;//采用取平均值的方法来防抖动
        scaleLevel=average/scaleBase;
        if(scaledRecord!=0){
            scaleLevel*=scaledRecord;//在上次的基础上进行放大(否则会跳回1倍大小重新开始缩放);
        }
        recView.setScaleX(scaleLevel);
        recView.setScaleY(scaleLevel);
        recView.invalidate();
//        recView.setVisibility(View.INVISIBLE);
//        recView.setVisibility(View.VISIBLE);
        return true;
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        recView.setPivotX(detector.getFocusX());
        recView.setPivotY(detector.getFocusY());
        average=scaleBase=detector.getCurrentSpan();
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
        scaledRecord=scaleLevel;
    }
}

   然后在主程序中,你要使用RecyclerView之前,先添加一下这个监听器:
    recyclerView.addOnItemTouchListener(new PdfScale());
    这样你的RecyclerView就能正常的用手势进行缩放了。  
 
   参考阅读:
   官方的API文档 https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.OnItemTouchListener
   另外,同学们,阅读API文档很重要啊,学好英语很重要啊………………

(欢迎转载,但转载请注明出处:https://blog.csdn.net/actionwind/article/details/112651614,引用请注明章节。)

你可能感兴趣的:(Android开发,安卓开发,RecyclerView缩放)