Обработка жестов касания и сжатия в одном и том же представлении

Я пытаюсь реализовать оба жеста (касание и масштабирование/разведение пальцев) в одном представлении.
Вот мой 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.

Любая помощь высоко ценится.


person Salman Khakwani    schedule 11.08.2014    source источник
comment
Вы можете использовать жестдетектор developer.android.com/training/gestures/detector.html Если вы пройдете полное обучение, вы сможете достичь того, что вам нужно   -  person Pasquale Anatriello    schedule 11.08.2014


Ответы (2)


Я решил эту проблему со следующей логикой:

Я взял флаг isPinchInProgress и выполнил код в моем прослушивателе жестов касания с некоторой задержкой, проверяя, является ли флаг 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;
}

Я надеюсь, что это поможет любому, кто сталкивается с той же проблемой.

person Salman Khakwani    schedule 13.08.2014

У меня была та же проблема, и я немного улучшил ответ Салмана Кваквани:

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)
}
person Helix    schedule 02.04.2021