【问题标题】:scaleGestureDetector.getScaleFactor() always returning 1.0 in Android 6.0scaleGestureDetector.getScaleFactor() 在 Android 6.0 中总是返回 1.0
【发布时间】:2016-09-20 12:47:37
【问题描述】:

我正在使用 ScaleGestureDetector 来检测捏合动作, 通过获取比例因子,如果小于 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);
}

}

【问题讨论】:

    标签: android android-6.0-marshmallow gesture-recognition


    【解决方案1】:

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

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

    如果你捏得很快,它会记录比上一个事件更大的跨度,并且会给你一个不同于 1 的因子。

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

    所以我创建了ScaleGestureDetector 的子类,并在其中覆盖了onTouchEvent()。在其中我跟踪两个手指,如果两个手指都在移动,我测量 start span 并保持它。我覆盖getScaleFactor() 并根据当前跨度与起始跨度计算因子。当任何一个手指被移除时,缩放完成;系数回到 1。

    【讨论】:

      【解决方案2】:

      我认为 onInterceptTouchEvent 没有调用。 您需要像这样在 TouchableWrapper 类中覆盖 onTouchEvent:

      @Override
      public boolean onTouchEvent(MotionEvent event) {
          mScaleGestureDetector.onTouchEvent(event);
          return true;
      }
      

      【讨论】:

      • 没用,一切都被正确调用了,我可以通过日志看到它。但我的问题在于 scaleGestureDetector.getScaleFactor() 的返回值在 5.0 和更低版本上一切都很好,但在 6.0 上它总是 1.0
      • @MohammadHaidar 你找到这个问题的原因了吗?
      猜你喜欢
      • 1970-01-01
      • 2020-06-24
      • 1970-01-01
      • 2019-09-28
      • 2013-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多