/******************************************************************************* * This file is part of RedReader. * * RedReader is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RedReader is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RedReader. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package org.quantumbadger.redreader.views.imageview; import android.view.MotionEvent; import org.quantumbadger.redreader.common.MutableFloatPoint2D; public class FingerTracker { public interface FingerListener { void onFingerDown(Finger finger); void onFingersMoved(); void onFingerUp(Finger finger); } private final Finger[] mFingers = new Finger[10]; private final FingerListener mListener; public FingerTracker(FingerListener mListener) { this.mListener = mListener; for(int i = 0; i < mFingers.length; i++) { mFingers[i] = new Finger(); } } public void onTouchEvent(MotionEvent event) { switch(event.getActionMasked()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: for(final Finger f : mFingers) { if(!f.mActive) { f.onDown(event); mListener.onFingerDown(f); break; } } break; case MotionEvent.ACTION_MOVE: for(Finger finger : mFingers) { if(finger.mActive) { finger.onMove(event); } } mListener.onFingersMoved(); break; case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_UP: final int id = event.getPointerId(event.getActionIndex()); for(final Finger f : mFingers) { if(f.mActive && f.mAndroidId == id) { f.onUp(event); mListener.onFingerUp(f); break; } } break; } } public class Finger { boolean mActive = false; int mAndroidId; final MutableFloatPoint2D mStartPos = new MutableFloatPoint2D(), mCurrentPos = new MutableFloatPoint2D(), mLastPos = new MutableFloatPoint2D(), mPosDifference = new MutableFloatPoint2D(), mTotalPosDifference = new MutableFloatPoint2D(); long mDownStartTime, mDownDuration; public void onDown(final MotionEvent event) { final int index = event.getActionIndex(); mActive = true; mAndroidId = event.getPointerId(index); mCurrentPos.set(event, index); mLastPos.set(mCurrentPos); mStartPos.set(mCurrentPos); mPosDifference.reset(); mTotalPosDifference.reset(); mDownStartTime = event.getDownTime(); mDownDuration = 0; } public void onMove(final MotionEvent event) { final int index = event.findPointerIndex(mAndroidId); if(index >= 0) { mLastPos.set(mCurrentPos); mCurrentPos.set(event, index); mCurrentPos.sub(mLastPos, mPosDifference); mCurrentPos.sub(mStartPos, mTotalPosDifference); mDownDuration = event.getEventTime() - mDownStartTime; } } public void onUp(final MotionEvent event) { mLastPos.set(mCurrentPos); mCurrentPos.set(event, event.getActionIndex()); mCurrentPos.sub(mLastPos, mPosDifference); mCurrentPos.sub(mStartPos, mTotalPosDifference); mDownDuration = event.getEventTime() - mDownStartTime; mActive = false; } } }