在同一视图上处理Tap和Pinch手势

时间:2014-08-11 11:35:35

标签: android gestures

我正在尝试在同一视图上实现两个手势(点按和缩放/缩放) 这是我的onTouchListener代码:

@Override
public boolean onTouch(View v, MotionEvent event) {
    // TODO Auto-generated method stub

    int touchCount = event.getPointerCount();

    switch(event.getAction())
    {

        case MotionEvent.ACTION_DOWN:
        {
            if(touchCount==1)
            {
                //do Autofocus here
                Log.v(TAG, "touchCount == 1");
                gestureDetector.onTouchEvent(event);
            }
        }
        break;

        case MotionEvent.ACTION_MOVE:
        {
            if(touchCount==2)
            {
                //scale gesture
                Log.v(TAG, "touchCount == 2");
                scaleGestureDetector.onTouchEvent(event);
            }   
        }
        break;

     }


手势代码:

    scaleGestureDetector = new ScaleGestureDetector(getActivity(), new ScaleGestureListener()); 
    gestureDetector = new GestureDetector(new Gesture());

private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        float scale = detector.getScaleFactor();

        Log.v(TAG, "scale = "+scale);

        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
        // TODO Auto-generated method stub
        super.onScaleEnd(detector);
    }
}

private class Gesture extends GestureDetector.SimpleOnGestureListener
{

    @Override
    public boolean onDown(MotionEvent event) {
        // TODO Auto-generated method stub

        Log.v(TAG, "onDown ");

        return super.onDown(event);
    }
};


问题: 即使我尝试使用Down Event,它始终会在我的Gesture听众中触发Pinch Gesture

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

我用以下逻辑解决了这个问题:

我带了一个标志isPinchInProgress并在我的Tap Gesture Listener中执行了一些延迟的代码,检查isPinchInProgress标志是真还是假。

boolean isPinchInProgress = false;

private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        // TODO Auto-generated method stub

        Log.d(TAG, "scaling started !");

        isPinchInProgress = true;

        return true;

    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {

        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
        // TODO Auto-generated method stub

        Log.d(TAG, "scaling end !");

        isPinchInProgress = false;

        super.onScaleEnd(detector);
    }
}

private class Gesture extends GestureDetector.SimpleOnGestureListener
{

    @Override
    public boolean onSingleTapConfirmed(final MotionEvent event) {
        // TODO Auto-generated method stub

        Log.v(TAG, "onSingleTapConfirmed ");

            new Handler().postDelayed(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    if(!isPinchInProgress)
                    {
                      //My code to be executed
                    }
                }
            }, 270);

        return true;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        // TODO Auto-generated method stub

        return onSingleTapConfirmed(e);
    }
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    // TODO Auto-generated method stub

    int touchCount = event.getPointerCount();

    if(v instanceof MY_CUSTOM_VIEW_CLASS)
    {

        switch(event.getAction())
        {

        case MotionEvent.ACTION_DOWN:
        {
            if(touchCount == 2)
            {
                return false;
            }
            else if(touchCount==1)
            {
                //do Autofocus here
                Log.v(TAG, "touchCount == 1");
                gestureDetector.onTouchEvent(event);
                return true;
            }
        }
        break;

        case MotionEvent.ACTION_MOVE:
        {
            if(touchCount==2)
            {
                //scale gesture
                Log.v(TAG, "touchCount == 2");

                scaleGestureDetector.onTouchEvent(event);

                return true;
            }
            else if(touchCount == 1)
            {
                return false;
            }
        }
        break;

        case MotionEvent.ACTION_UP:
        {
            scaleGestureDetector.onTouchEvent(event);
            return true;
        }

        }

    }

    return false;
}

我希望这有助于任何面临同样问题的人。

答案 1 :(得分:0)

我遇到了同样的问题并改进了一些 Salman Kwakwani 的回答:

class ScaleAndClickGestureDetector(val context: Context, val listener: Listener) : ScaleGestureDetector.OnScaleGestureListener {

    companion object {
        private const val DELAY_BEFORE_CLICK_CONFIRMED = 270L
    }

    interface Listener {
        fun onClick()
        fun onScale(scaleFactor: Float)
    }

    private val scaleGestureDetector = ScaleGestureDetector(context, this)
    private var pinching = false

    override fun onScale(detector: ScaleGestureDetector?) = false

    override fun onScaleBegin(detector: ScaleGestureDetector?): Boolean {
        pinching = true
        return true
    }

    override fun onScaleEnd(detector: ScaleGestureDetector?) {
        pinching = false
        detector?.scaleFactor?.let {
            listener.onScale(it)
        }
    }

    fun onTouchEvent(event: MotionEvent): Boolean {
        return if (event.pointerCount > 1) {
            scaleGestureDetector.onTouchEvent(event)
        } else if (event.action == MotionEvent.ACTION_DOWN && !pinching) {
            Handler().postDelayed({
                if (!pinching) {
                    listener.onClick()
                }
            }, DELAY_BEFORE_CLICK_CONFIRMED)
            true
        } else {
            false
        }
    }
}

然后使用它:

val scaleAndClickGestureDetector = ScaleAndClickGestureDetector(context, object : ScaleAndClickGestureDetector.Listener {
      override fun onClick() {}
      override fun onScale(scaleFactor: Float) {}
})

yourView.setOnTouchListener { v, event ->
     scaleAndClickGestureDetector.onTouchEvent(event)
}