我正在使用ScaleGestureDetector来检测捏和捏 Action ,
通过获得比例因子,如果小于1,则将其缩小,反之亦然。

但是问题在于,在Android 6.0上,比例因子始终为1.0,这使得无法区分是捏还是捏。

在此先感谢您的帮助。

import android.content.Context;
import android.os.Handler;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.MotionEventCompat;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.VelocityTracker;
import android.widget.FrameLayout;

public class TouchableWrapper extends FrameLayout
{
    private GestureDetectorCompat mGestureDetector;
    private ScaleGestureDetector mScaleGestureDetector;
    private VelocityTracker mVelocityTracker;
    private boolean acceptEvents=true;
    ScaleGestureDetector temp;


private final GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener()
{

    @Override
    public boolean onDoubleTap(MotionEvent e)
    {
        EventBus_Singleton.getInstance().post(new EventBus_Poster(Constants.MAP_DOUBLE_TOUCHED));
        return true;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        return super.onDoubleTapEvent(e);
    }



};

private final ScaleGestureDetector.OnScaleGestureListener mScaleGestureListener = new ScaleGestureDetector.SimpleOnScaleGestureListener()
{
    /**
     * This is the active focal point in terms of the viewport. Could be a local
     * variable but kept here to minimize per-frame allocations.
     */

    float startingSpan;
    float startFocusX;
    float startFocusY;

    @Override
    public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector)
    {

        temp=scaleGestureDetector;
        startingSpan = scaleGestureDetector.getCurrentSpan();
        startFocusX = scaleGestureDetector.getFocusX();
        startFocusY = scaleGestureDetector.getFocusY();

        return true;
    }

    @Override
    public boolean onScale(ScaleGestureDetector scaleGestureDetector)
    {
        super.onScale(scaleGestureDetector);

        float scale = scaleGestureDetector.getScaleFactor();
        //mVelocityTracker.computeCurrentVelocity(1000);



        if(acceptEvents)
        {

            Log.e("scaleGestureDetector.getCurrentSpan()", scaleGestureDetector.getCurrentSpan()+"");
            Log.e("startingSpan", startingSpan+"");
            Log.e("onScale",scale+"");

            if (scale <= 1.0)
            {
                acceptEvents = false;
                EventBus_Singleton.getInstance().post(new EventBus_Poster(Constants.MAP_ZOOMED_OUT));
            }
            else
            {
                acceptEvents = false;
                EventBus_Singleton.getInstance().post(new EventBus_Poster(Constants.MAP_ZOOMED_IN));
            }
        }

        return true;
    }
};

public TouchableWrapper(Context context)
{
    super(context);
    mScaleGestureDetector = new ScaleGestureDetector(context, mScaleGestureListener);
    mGestureDetector = new GestureDetectorCompat(context, mGestureListener);
    mVelocityTracker = VelocityTracker.obtain();
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
    mGestureDetector.onTouchEvent(ev);
    //Log.e("Motion Event pointer count",ev.getPointerCount()+"");


    int action = MotionEventCompat.getActionMasked(ev);

    switch (action)
    {
        case (MotionEvent.ACTION_DOWN):
            Log.e("MotionEvent", "Action was DOWN");
            break;
        case (MotionEvent.ACTION_MOVE):
            //Log.e("MotionEvent", "Action was MOVE");
            /*if(acceptEvents)
            {
                if(MotionEventCompat.getPointerCount(ev)==2)
                {

                    x1=MotionEventCompat.getX(ev,0);
                    x2=MotionEventCompat.getX(ev,1);
                    y1=MotionEventCompat.getY(ev,0);
                    y2=MotionEventCompat.getY(ev,1);


                    if(differenceX==0||differenceY==0)
                    {
                        differenceX=Math.abs(x1-x2);
                        differenceY=Math.abs(y1-y2);
                    }
                    else
                    {
                        differenceXPrime=Math.abs(x1-x2);
                        differenceYPrime=Math.abs(y1-y2);


                        if (differenceXPrime-differenceX>100 || differenceYPrime-differenceY>100)
                        {
                            Log.e("Zoomed out","differenceX:"+differenceX+"         differenceXPrime:"+differenceXPrime+"           differenceY:"+differenceY+"            differenceYPrime:"+differenceYPrime);
                            differenceX=0;
                            differenceY=0;
                            acceptEvents=false;
                            EventBus_Singleton.getInstance().post(new EventBus_Poster(Constants.MAP_ZOOMED_IN));

                        }
                        else if(differenceX-differenceXPrime>100 || differenceY-differenceYPrime>100)
                        {
                            Log.e("Zoomed in","differenceX:"+differenceX+"         differenceXPrime:"+differenceXPrime+"           differenceY:"+differenceY+"            differenceYPrime:"+differenceYPrime);
                            differenceX=0;
                            differenceY=0;
                            acceptEvents=false;
                            EventBus_Singleton.getInstance().post(new EventBus_Poster(Constants.MAP_ZOOMED_OUT));
                        }
                    }
                }
            }*/

            break;
        case (MotionEvent.ACTION_UP):
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    EventBus_Singleton.getInstance().post(new EventBus_Poster(Constants.ENABLE_MAP_GESTURE));
                    acceptEvents=true;
                }
            },300);

            Log.e("MotionEvent", "Action was UP");
            break;
        case (MotionEvent.ACTION_POINTER_UP):
            Log.e("MotionEvent", "Action was POINTER UP");
            break;
        case (MotionEvent.ACTION_POINTER_DOWN):
            EventBus_Singleton.getInstance().post(new EventBus_Poster(Constants.DISABLE_MAP_GESTURE));
            Log.e("MotionEvent", "Action was POINTER DOWN");
            break;
        case (MotionEvent.ACTION_CANCEL):
            Log.e("MotionEvent", "Action was CANCEL");
            break;
        case (MotionEvent.ACTION_OUTSIDE):
            Log.e("MotionEvent", "Movement occurred outside bounds of current screen element");
            break;
    }
    mVelocityTracker.addMovement(ev);
    mScaleGestureDetector.onTouchEvent(ev);
    return super.onInterceptTouchEvent(ev);
}

}

最佳答案

我认为问题在于,当您缓慢地执行捏手势时,此类会丢弃手指之间较小的跨度增量。它只担心跨度的巨大差异。

如果慢慢捏,它将记录许多不同的触摸移动事件,每个事件的跨度(手指之间)仅与上一个事件稍有不同。它认为跨度没有变化,因此比例因子为1。

如果您快速捏,它将记录比上一个事件更大的跨度,并且会给您一个不同于1的因数。

在我的解决方案中,我自定义类。我自己计算比例因子。只要不捏,比例因子就是1。然后,当您开始捏捏时,比例因子是从捏捏手势的开始以前的触摸事件的而不是计算的。

因此,我创建了ScaleGestureDetector的子类,并在其中重写onTouchEvent()。在其中,我跟踪两只手指,如果两只手指都在移动,则测量的起始跨距并保持它。我覆盖了getScaleFactor(),并且根据当前跨度与起始跨度来计算因子。当任何一根手指移开时,缩放就完成了。该系数回到1。

10-06 05:50