/**
* @file MotionManager.java
*
* @revision: none
*
* @version 0.0.01
* @author: Zenki (zhajun), zenki2001cn@163.com
* @date: 2011-6-4 下午05:28:42
*/
package com.easyview.ebook.reader.engine.util.motion;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import com.easyview.ebook.reader.engine.util.Logger;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
/**
*
*/
public class MotionManager implements IMotionManager {
static private final String TAG = "MotionManager";
private Context mContext;
private View mAttachedView;
private volatile ShortClickRunnable myPendingShortClickRunnable;
private volatile LongClickRunnable myPendingLongClickRunnable;
private boolean mRunMode = false;
private boolean mSupportDoubleTap = false;
private volatile boolean myLongClickPerformed;
private volatile boolean myPendingPress;
private volatile boolean myPendingDoubleTap;
private int myPressedX, myPressedY;
private boolean myScreenIsTouched;
private final int MSG_LONG_PRESS = 1;
private HashMap<String, IMotionCall> mMotionCallList = new HashMap<String, IMotionCall>();
private Handler H = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_LONG_PRESS:
Logger.dLog(TAG, "handleMessage FINGER_LONG_PRESS ");
doMotionCall(MOTION_TYPE.FINGER_LONG_PRESS, msg.arg1, msg.arg2);
break;
default:
break;
}
super.handleMessage(msg);
}
};
public MotionManager(Context ctx, View attachedView) {
mContext = ctx;
mAttachedView = attachedView;
init();
}
private void init() {
for (int i = 0; i < MOTION_TYPE.MOTION_TYPE_SIZE + 1; i++) {
mMotionCallList.put(String.valueOf(i), new IMotionCall() {
@Override
public void doMotion(int x, int y) {
Logger.dLog(TAG, "doMotionCall motion x = " + x + " y = "
+ y);
}
});
}
}
private class LongClickRunnable implements Runnable {
public void run() {
if (mAttachedView != null) {
if (mAttachedView.performLongClick()) {
myLongClickPerformed = true;
Message msg = Message.obtain();
msg.arg1 = mX;
msg.arg2 = mY;
msg.what = MSG_LONG_PRESS;
H.sendMessage(msg);
}
}
}
}
private void postLongClickRunnable() {
// Logger.dLog(
// TAG,
// "postLongClickRunnable timeout = "
// + ViewConfiguration.getLongPressTimeout());
myLongClickPerformed = false;
myPendingPress = false;
if (myPendingLongClickRunnable == null) {
myPendingLongClickRunnable = new LongClickRunnable();
}
if (mAttachedView != null) {
mAttachedView.postDelayed(myPendingLongClickRunnable,
2 * ViewConfiguration.getLongPressTimeout());
}
}
private class ShortClickRunnable implements Runnable {
public void run() {
Logger.dLog(TAG, "ShortClickRunnable run");
// mAttachedView.onFingerSingleTap(myPressedX, myPressedY);
myPendingPress = false;
myPendingShortClickRunnable = null;
}
}
private int mCurMotionType;
int mX;
int mY;
@Override
public int doRunMode(MotionEvent event) {
mX = (int) event.getX();
mY = (int) event.getY();
int action = event.getAction();
// Logger.dLog(TAG, "action = " + action);
switch (action) {
case MotionEvent.ACTION_UP:
Logger.eLog(TAG, "ACTION_UP ^^^^^^^^^^^^^ ");
if (myPendingDoubleTap) {
// view.onFingerDoubleTap(x, y);
mCurMotionType = MOTION_TYPE.FINGER_DOUBLE_TAP;
doMotionCall(mCurMotionType, mX, mY);
}
if (myLongClickPerformed) {
// view.onFingerReleaseAfterLongPress(x, y);
mCurMotionType = MOTION_TYPE.FINGER_RELEASE_AFTER_LONG_PRESS;
doMotionCall(mCurMotionType, mX, mY);
} else {
if (myPendingLongClickRunnable != null) {
if (mAttachedView != null) {
mAttachedView
.removeCallbacks(myPendingLongClickRunnable);
}
myPendingLongClickRunnable = null;
}
if (myPendingPress) {
if (supportDoubleTap() && (mAttachedView != null)) {
if (myPendingShortClickRunnable == null) {
myPendingShortClickRunnable = new ShortClickRunnable();
}
mAttachedView.postDelayed(myPendingShortClickRunnable,
ViewConfiguration.getDoubleTapTimeout());
} else {
// view.onFingerSingleTap(x, y);
mCurMotionType = MOTION_TYPE.FINGER_SINGLE_TAP;
doMotionCall(mCurMotionType, mX, mY);
}
} else {
// view.onFingerRelease(x, y);
mCurMotionType = MOTION_TYPE.FINGER_SINGLE_RELEASE;
doMotionCall(mCurMotionType, mX, mY);
}
}
myPendingDoubleTap = false;
myPendingPress = false;
myScreenIsTouched = false;
break;
case MotionEvent.ACTION_DOWN:
if (myPendingShortClickRunnable != null) {
Logger.eLog(TAG, "ACTION_DOWN DOUBLE VVVVVVVVVVVVV");
if (mAttachedView != null) {
mAttachedView.removeCallbacks(myPendingShortClickRunnable);
}
myPendingShortClickRunnable = null;
myPendingDoubleTap = true;
} else {
Logger.eLog(TAG, "ACTION_DOWN PRESS VVVVVVVVVVVVV");
postLongClickRunnable();
myPendingPress = true;
}
myScreenIsTouched = true;
myPressedX = mX;
myPressedY = mY;
break;
case MotionEvent.ACTION_MOVE: {
final int slop = ViewConfiguration.get(
mContext.getApplicationContext()).getScaledTouchSlop();
// Logger.eLog(TAG, "ACTION_MOVE >>>>>>>>>>>>>> slop = " + slop);
final boolean isAMove = Math.abs(myPressedX - mX) > slop
|| Math.abs(myPressedY - mY) > slop;
if (isAMove) {
myPendingDoubleTap = false;
}
if (myLongClickPerformed) {
mCurMotionType = MOTION_TYPE.FINGER_MOVE_AFTER_LONG_PRESS;
doMotionCall(mCurMotionType, mX, mY);
} else {
if (myPendingPress) {
if (isAMove) {
if (myPendingShortClickRunnable != null) {
if (mAttachedView != null) {
mAttachedView
.removeCallbacks(myPendingShortClickRunnable);
}
myPendingShortClickRunnable = null;
}
if (myPendingLongClickRunnable != null) {
if (mAttachedView != null) {
mAttachedView
.removeCallbacks(myPendingLongClickRunnable);
}
}
mCurMotionType = MOTION_TYPE.FINGER_PRESS;
doMotionCall(mCurMotionType, myPressedX, myPressedY);
myPendingPress = false;
}
}
if (!myPendingPress) {
mCurMotionType = MOTION_TYPE.FINGER_MOVE;
doMotionCall(mCurMotionType, mX, mY);
}
}
break;
}
}
Logger.eLog(TAG, "motion type =========== " + mCurMotionType);
return mCurMotionType;
}
public void setDoubleTap(boolean doubleTap) {
mSupportDoubleTap = doubleTap;
}
public boolean supportDoubleTap() {
return mSupportDoubleTap;
}
private void doMotionCall(int type, int x, int y) {
if (mRunMode && (mMotionCallList != null)
&& mMotionCallList.containsKey(String.valueOf(type))) {
IMotionCall call = mMotionCallList.get(String.valueOf(type));
if (call != null) {
call.doMotion(x, y);
}
}
}
public boolean getScreenTouched() {
return myScreenIsTouched;
}
@Override
public void registerMotionCall(int type, IMotionCall call) {
mMotionCallList.put(String.valueOf(type), call);
}
@Override
public void setRunMode(boolean run) {
mRunMode = run;
}
}