package org.andengine.input.touch.detector; import org.andengine.input.touch.TouchEvent; /** * (c) 2010 Nicolas Gramlich * (c) 2011 Zynga Inc. * * @author Nicolas Gramlich * @since 14:29:59 - 16.08.2010 */ public class ScrollDetector extends BaseDetector { // =========================================================== // Constants // =========================================================== private static final float TRIGGER_SCROLL_MINIMUM_DISTANCE_DEFAULT = 10; // =========================================================== // Fields // =========================================================== private float mTriggerScrollMinimumDistance; private final IScrollDetectorListener mScrollDetectorListener; private int mPointerID = TouchEvent.INVALID_POINTER_ID; private boolean mTriggering; private float mLastX; private float mLastY; // =========================================================== // Constructors // =========================================================== public ScrollDetector(final IScrollDetectorListener pScrollDetectorListener) { this(ScrollDetector.TRIGGER_SCROLL_MINIMUM_DISTANCE_DEFAULT, pScrollDetectorListener); } public ScrollDetector(final float pTriggerScrollMinimumDistance, final IScrollDetectorListener pScrollDetectorListener) { this.mTriggerScrollMinimumDistance = pTriggerScrollMinimumDistance; this.mScrollDetectorListener = pScrollDetectorListener; } // =========================================================== // Getter & Setter // =========================================================== public float getTriggerScrollMinimumDistance() { return this.mTriggerScrollMinimumDistance; } public void setTriggerScrollMinimumDistance(final float pTriggerScrollMinimumDistance) { this.mTriggerScrollMinimumDistance = pTriggerScrollMinimumDistance; } // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== @Override public void reset() { if(this.mTriggering) { this.mScrollDetectorListener.onScrollFinished(this, this.mPointerID, 0, 0); } this.mLastX = 0; this.mLastY = 0; this.mTriggering = false; this.mPointerID = TouchEvent.INVALID_POINTER_ID; } @Override public boolean onManagedTouchEvent(final TouchEvent pSceneTouchEvent) { final float touchX = this.getX(pSceneTouchEvent); final float touchY = this.getY(pSceneTouchEvent); switch(pSceneTouchEvent.getAction()) { case TouchEvent.ACTION_DOWN: this.prepareScroll(pSceneTouchEvent.getPointerID(), touchX, touchY); return true; case TouchEvent.ACTION_MOVE: if(this.mPointerID == TouchEvent.INVALID_POINTER_ID) { this.prepareScroll(pSceneTouchEvent.getPointerID(), touchX, touchY); return true; } else if(this.mPointerID == pSceneTouchEvent.getPointerID()) { final float distanceX = touchX - this.mLastX; final float distanceY = touchY - this.mLastY; final float triggerScrollMinimumDistance = this.mTriggerScrollMinimumDistance; if(this.mTriggering || Math.abs(distanceX) > triggerScrollMinimumDistance || Math.abs(distanceY) > triggerScrollMinimumDistance) { if(!this.mTriggering) { this.triggerOnScrollStarted(distanceX, distanceY); } else { this.triggerOnScroll(distanceX, distanceY); } this.mLastX = touchX; this.mLastY = touchY; this.mTriggering = true; } return true; } else { return false; } case TouchEvent.ACTION_UP: case TouchEvent.ACTION_CANCEL: if(this.mPointerID == pSceneTouchEvent.getPointerID()) { final float distanceX = touchX - this.mLastX; final float distanceY = touchY - this.mLastY; if(this.mTriggering) { this.triggerOnScrollFinished(distanceX, distanceY); } this.mPointerID = TouchEvent.INVALID_POINTER_ID; } return true; default: return false; } } // =========================================================== // Methods // =========================================================== private void prepareScroll(final int pPointerID, final float pTouchX, final float pTouchY) { this.mLastX = pTouchX; this.mLastY = pTouchY; this.mTriggering = false; this.mPointerID = pPointerID; } private void triggerOnScrollStarted(final float pDistanceX, final float pDistanceY) { if(this.mPointerID != TouchEvent.INVALID_POINTER_ID) { this.mScrollDetectorListener.onScrollStarted(this, this.mPointerID, pDistanceX, pDistanceY); } } private void triggerOnScroll(final float pDistanceX, final float pDistanceY) { if(this.mPointerID != TouchEvent.INVALID_POINTER_ID) { this.mScrollDetectorListener.onScroll(this, this.mPointerID, pDistanceX, pDistanceY); } } private void triggerOnScrollFinished(final float pDistanceX, final float pDistanceY) { this.mTriggering = false; if(this.mPointerID != TouchEvent.INVALID_POINTER_ID) { this.mScrollDetectorListener.onScrollFinished(this, this.mPointerID, pDistanceX, pDistanceY); } } protected float getX(final TouchEvent pTouchEvent) { return pTouchEvent.getX(); } protected float getY(final TouchEvent pTouchEvent) { return pTouchEvent.getY(); } // =========================================================== // Inner and Anonymous Classes // =========================================================== public static interface IScrollDetectorListener { // =========================================================== // Constants // =========================================================== // =========================================================== // Methods // =========================================================== public void onScrollStarted(final ScrollDetector pScollDetector, final int pPointerID, final float pDistanceX, final float pDistanceY); public void onScroll(final ScrollDetector pScollDetector, final int pPointerID, final float pDistanceX, final float pDistanceY); public void onScrollFinished(final ScrollDetector pScollDetector, final int pPointerID, final float pDistanceX, final float pDistanceY); } }