下面列出了android.view.MotionEvent#getEventTime ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
protected void updateStateByEvent(MotionEvent curr){
final MotionEvent prev = mPrevEvent;
// Reset mCurrEvent
if (mCurrEvent != null) {
mCurrEvent.recycle();
mCurrEvent = null;
}
mCurrEvent = MotionEvent.obtain(curr);
// Delta time
mTimeDelta = curr.getEventTime() - prev.getEventTime();
// Pressure
mCurrPressure = curr.getPressure(curr.getActionIndex());
mPrevPressure = prev.getPressure(prev.getActionIndex());
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (callback.get() != null) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN && !isInResizeMode) {
isInResizeMode = true;
callback.get().onResizeStarted();
oldX = motionEvent.getRawX();
oldY = motionEvent.getRawY();
} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
this.callback.get().onHandleMoved(motionEvent.getRawX(), motionEvent.getRawY(), oldX, oldY,
mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels);
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
if (isInResizeMode) {
callback.get().onResizeFinished();
isInResizeMode = false;
}
if (motionEvent.getEventTime() - motionEvent.getDownTime() < 200)
view.performClick();
}
return true;
}
return false;
}
protected void updateStateByEvent(MotionEvent curr){
final MotionEvent prev = mPrevEvent;
// Reset mCurrEvent
if (mCurrEvent != null) {
mCurrEvent.recycle();
mCurrEvent = null;
}
mCurrEvent = MotionEvent.obtain(curr);
// Delta time
mTimeDelta = curr.getEventTime() - prev.getEventTime();
// Pressure
mCurrPressure = curr.getPressure(curr.getActionIndex());
mPrevPressure = prev.getPressure(prev.getActionIndex());
}
static boolean isClickEvent(float startX, float startY, MotionEvent event) {
float duration = event.getEventTime() - event.getDownTime();
if (duration > MAX_CLICK_DURATION) {
return false;
}
float differenceX = Math.abs(startX - event.getX());
float differenceY = Math.abs(startY - event.getY());
return !(differenceX > MAX_CLICK_DISTANCE || differenceY > MAX_CLICK_DISTANCE);
}
private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp,
MotionEvent secondDown) {
if (!mAlwaysInBiggerTapRegion) {
return false;
}
if (secondDown.getEventTime() - firstUp.getEventTime() > DOUBLE_TAP_TIMEOUT) {
return false;
}
int deltaX = (int) firstDown.getX() - (int) secondDown.getX();
int deltaY = (int) firstDown.getY() - (int) secondDown.getY();
return (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare);
}
void cancelLongPressIfNeeded(MotionEvent ev) {
if (!hasPendingMessage() ||
mCurrentDownEvent == null || ev.getDownTime() != mCurrentDownEvent.getDownTime()) {
return;
}
final int action = ev.getAction();
final float y = ev.getY();
final float x = ev.getX();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_MOVE:
final int deltaX = (int) (x - mCurrentDownEvent.getX());
final int deltaY = (int) (y - mCurrentDownEvent.getY());
int distance = (deltaX * deltaX) + (deltaY * deltaY);
if (distance > mTouchSlopSquare) {
cancelLongPress();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (calculateLongPressTimeoutTime(mCurrentDownEvent) > ev.getEventTime()) {
cancelLongPress();
}
break;
default:
break;
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
final int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN: {
removeAllCallbacks();
mInputText.setVisibility(View.INVISIBLE);
mLastDownOrMoveEventY = mLastDownEventY = event.getY();
mLastDownEventTime = event.getEventTime();
mIngonreMoveEvents = false;
if (mLastDownEventY < mTopSelectionDividerTop) {
if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) {
mPressedStateHelper.buttonPressDelayed(PressedStateHelper.BUTTON_DECREMENT);
}
} else if (mLastDownEventY > mBottomSelectionDividerBottom) {
if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) {
mPressedStateHelper.buttonPressDelayed(PressedStateHelper.BUTTON_INCREMENT);
}
}
getParent().requestDisallowInterceptTouchEvent(true);
if (!mFlingScroller.isFinished()) {
mFlingScroller.forceFinished(true);
mAdjustScroller.forceFinished(true);
onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
} else if (!mAdjustScroller.isFinished()) {
mFlingScroller.forceFinished(true);
mAdjustScroller.forceFinished(true);
} else if (mLastDownEventY < mTopSelectionDividerTop) {
postChangeCurrentByOneFromLongPress(false, ViewConfiguration.getLongPressTimeout());
} else if (mLastDownEventY > mBottomSelectionDividerBottom) {
postChangeCurrentByOneFromLongPress(true, ViewConfiguration.getLongPressTimeout());
}
return true;
}
}
return false;
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
if (((ChatMessagesAdapter) mRecyclerView.getAdapter()).getSelectedItems().size() > 0)
return false;
if (e.getActionMasked() == MotionEvent.ACTION_DOWN) {
mTouchDownX = e.getX();
mTouchDownY = e.getY();
hideActionModeForSelection();
}
if (e.getActionMasked() == MotionEvent.ACTION_UP ||
e.getActionMasked() == MotionEvent.ACTION_CANCEL) {
if (!mSelectionLongPressMode &&
e.getEventTime() - e.getDownTime() < MAX_CLICK_DURATION &&
Math.sqrt(Math.pow(e.getX() - mTouchDownX, 2) +
Math.pow(e.getY() - mTouchDownY, 2)) < MAX_CLICK_DISTANCE *
Resources.getSystem().getDisplayMetrics().density) {
clearSelection();
}
mRecyclerView.getParent().requestDisallowInterceptTouchEvent(false);
mSelectionLongPressMode = false;
if (mSelectionStartId != -1) {
showHandles();
showActionMode();
}
}
if (mSelectionLongPressMode) {
if (e.getActionMasked() == MotionEvent.ACTION_UP)
mScroller.setScrollDir(0);
else if (e.getY() < 0)
mScroller.setScrollDir(-1);
else if (e.getY() > mRecyclerView.getHeight())
mScroller.setScrollDir(1);
else
mScroller.setScrollDir(0);
}
return handleSelection(e.getX(), e.getY(), e.getRawX(), e.getRawY());
}
private static MotionEvent transformEventOld(MotionEvent e, Matrix m) {
long downTime = e.getDownTime();
long eventTime = e.getEventTime();
int action = e.getAction();
int pointerCount = e.getPointerCount();
int[] pointerIds = getPointerIds(e);
PointerCoords[] pointerCoords = getPointerCoords(e);
int metaState = e.getMetaState();
float xPrecision = e.getXPrecision();
float yPrecision = e.getYPrecision();
int deviceId = e.getDeviceId();
int edgeFlags = e.getEdgeFlags();
int source = e.getSource();
int flags = e.getFlags();
// Copy the x and y coordinates into an array, map them, and copy back.
float[] xy = new float[pointerCoords.length * 2];
for (int i = 0; i < pointerCount;i++) {
xy[2 * i] = pointerCoords[i].x;
xy[2 * i + 1] = pointerCoords[i].y;
}
m.mapPoints(xy);
for (int i = 0; i < pointerCount;i++) {
pointerCoords[i].x = xy[2 * i];
pointerCoords[i].y = xy[2 * i + 1];
pointerCoords[i].orientation = transformAngle(
m, pointerCoords[i].orientation);
}
MotionEvent n = MotionEvent.obtain(downTime, eventTime, action,
pointerCount, pointerIds, pointerCoords, metaState, xPrecision,
yPrecision, deviceId, edgeFlags, source, flags);
return n;
}
private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp, MotionEvent secondDown) {
if (!this.mAlwaysInBiggerTapRegion || secondDown.getEventTime() - firstUp.getEventTime() > ((long) DOUBLE_TAP_TIMEOUT)) {
return false;
}
int deltaX = ((int) firstDown.getX()) - ((int) secondDown.getX());
int deltaY = ((int) firstDown.getY()) - ((int) secondDown.getY());
if ((deltaX * deltaX) + (deltaY * deltaY) < this.mDoubleTapSlopSquare) {
return true;
}
return false;
}
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;
}
}
@Override
protected void onHoverMove(final MotionEvent event) {
super.onHoverMove(event);
final int actionIndex = event.getActionIndex();
final int x = (int)event.getX(actionIndex);
final int y = (int)event.getY(actionIndex);
final int pointerId = event.getPointerId(actionIndex);
final long eventTime = event.getEventTime();
mKeyboardView.onMoveEvent(x, y, pointerId, eventTime);
}
/** Handles the touch event */
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mIsCapturingGesture = true;
mIsClickCandidate = true;
mActionDownTime = event.getEventTime();
mActionDownX = event.getX();
mActionDownY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
if (Math.abs(event.getX() - mActionDownX) > mSingleTapSlopPx
|| Math.abs(event.getY() - mActionDownY) > mSingleTapSlopPx) {
mIsClickCandidate = false;
}
break;
case MotionEvent.ACTION_CANCEL:
mIsCapturingGesture = false;
mIsClickCandidate = false;
break;
case MotionEvent.ACTION_UP:
mIsCapturingGesture = false;
if (Math.abs(event.getX() - mActionDownX) > mSingleTapSlopPx
|| Math.abs(event.getY() - mActionDownY) > mSingleTapSlopPx) {
mIsClickCandidate = false;
}
if (mIsClickCandidate) {
if (event.getEventTime() - mActionDownTime <= ViewConfiguration.getLongPressTimeout()) {
if (mClickListener != null) {
mClickListener.onClick();
}
} else {
// long click, not handled
}
}
mIsClickCandidate = false;
break;
}
return true;
}
public boolean onUtilsStop(View view, MotionEvent event) {
int x = (int) event.getRawX();
int y = (int) event.getRawY();
int vx = 0, vy = 0;
if (velocityTracker != null) {
velocityTracker.computeCurrentVelocity(1000, maximumFlingVelocity);
vx = (int) velocityTracker.getXVelocity();
vy = (int) velocityTracker.getYVelocity();
velocityTracker.recycle();
if (Math.abs(vx) < minimumFlingVelocity) {
vx = 0;
}
if (Math.abs(vy) < minimumFlingVelocity) {
vy = 0;
}
velocityTracker = null;
}
view.setPressed(false);
boolean consumeStop = onStop(view, direction, x, y, x - downX, y - downY, vx, vy, event);
if (event.getAction() == MotionEvent.ACTION_UP) {
if (state == STATE_DOWN) {
if (event.getEventTime() - event.getDownTime() <= MIN_TAP_TIME) {
view.performClick();
} else {
view.performLongClick();
}
}
}
resetTouch(-1, -1);
return consumeStop;
}
private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp, MotionEvent secondDown) {
if (!mAlwaysInBiggerTapRegion) {
return false;
}
final long deltaTime = secondDown.getEventTime() - firstUp.getEventTime();
if (deltaTime > DOUBLE_TAP_TIMEOUT || deltaTime < DOUBLE_TAP_MIN_TIME) {
return false;
}
int deltaX = (int) firstDown.getX() - (int) secondDown.getX();
int deltaY = (int) firstDown.getY() - (int) secondDown.getY();
int slopSquare = mDoubleTapSlopSquare;
return (deltaX * deltaX + deltaY * deltaY < slopSquare);
}
/**
* Gets all the touch events and updates dragging related logic. Note that if this app menu
* is initiated by software UI control, then the control should set onTouchListener and forward
* all the events to this method because the initial UI control that processed ACTION_DOWN will
* continue to get all the subsequent events.
*
* @param event Touch event to be processed.
* @param button Button that received the touch event.
* @return Whether the event is handled.
*/
boolean handleDragging(MotionEvent event, View button) {
if (!mAppMenu.isShowing() || !mDragScrolling.isRunning()) return false;
// We will only use the screen space coordinate (rawX, rawY) to reduce confusion.
// This code works across many different controls, so using local coordinates will be
// a disaster.
final float rawX = event.getRawX();
final float rawY = event.getRawY();
final int roundedRawX = Math.round(rawX);
final int roundedRawY = Math.round(rawY);
final int eventActionMasked = event.getActionMasked();
final long timeSinceDown = event.getEventTime() - event.getDownTime();
final ListView listView = mAppMenu.getPopup().getListView();
mLastTouchX = rawX;
mLastTouchY = rawY;
mMenuButtonScreenCenterY = getScreenVisibleRect(button).centerY();
if (eventActionMasked == MotionEvent.ACTION_CANCEL) {
mAppMenu.dismiss();
return true;
} else if (eventActionMasked == MotionEvent.ACTION_UP) {
nativeRecordAppMenuTouchDuration(timeSinceDown);
}
mIsSingleTapCanceled |= timeSinceDown > mTapTimeout;
mIsSingleTapCanceled |= !pointInView(button, event.getX(), event.getY(), mScaledTouchSlop);
if (!mIsSingleTapCanceled && eventActionMasked == MotionEvent.ACTION_UP) {
RecordUserAction.record("MobileUsingMenuBySwButtonTap");
finishDragging();
}
// After this line, drag scrolling is happening.
if (!mDragScrolling.isRunning()) return false;
boolean didPerformClick = false;
int itemAction = ITEM_ACTION_CLEAR_HIGHLIGHT_ALL;
switch (eventActionMasked) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
itemAction = ITEM_ACTION_HIGHLIGHT;
break;
case MotionEvent.ACTION_UP:
itemAction = ITEM_ACTION_PERFORM;
break;
default:
break;
}
didPerformClick = menuItemAction(roundedRawX, roundedRawY, itemAction);
if (eventActionMasked == MotionEvent.ACTION_UP && !didPerformClick) {
RecordUserAction.record("MobileUsingMenuBySwButtonDragging");
mAppMenu.dismiss();
} else if (eventActionMasked == MotionEvent.ACTION_MOVE) {
// Auto scrolling on the top or the bottom of the listView.
if (listView.getHeight() > 0) {
float autoScrollAreaRatio = Math.min(AUTO_SCROLL_AREA_MAX_RATIO,
mItemRowHeight * 1.2f / listView.getHeight());
float normalizedY =
(rawY - getScreenVisibleRect(listView).top) / listView.getHeight();
if (normalizedY < autoScrollAreaRatio) {
// Top
mDragScrollingVelocity = (normalizedY / autoScrollAreaRatio - 1.0f)
* mAutoScrollFullVelocity;
} else if (normalizedY > 1.0f - autoScrollAreaRatio) {
// Bottom
mDragScrollingVelocity = ((normalizedY - 1.0f) / autoScrollAreaRatio + 1.0f)
* mAutoScrollFullVelocity;
} else {
// Middle or not scrollable.
mDragScrollingVelocity = 0.0f;
}
}
}
return true;
}
/**
* Gets all the touch events and updates dragging related logic. Note that if this app menu
* is initiated by software UI control, then the control should set onTouchListener and forward
* all the events to this method because the initial UI control that processed ACTION_DOWN will
* continue to get all the subsequent events.
*
* @param event Touch event to be processed.
* @param button Button that received the touch event.
* @return Whether the event is handled.
*/
boolean handleDragging(MotionEvent event, View button) {
if (!mAppMenu.isShowing() || !mDragScrolling.isRunning()) return false;
// We will only use the screen space coordinate (rawX, rawY) to reduce confusion.
// This code works across many different controls, so using local coordinates will be
// a disaster.
final float rawX = event.getRawX();
final float rawY = event.getRawY();
final int roundedRawX = Math.round(rawX);
final int roundedRawY = Math.round(rawY);
final int eventActionMasked = event.getActionMasked();
final long timeSinceDown = event.getEventTime() - event.getDownTime();
final ListView listView = mAppMenu.getPopup().getListView();
mLastTouchX = rawX;
mLastTouchY = rawY;
mMenuButtonScreenCenterY = getScreenVisibleRect(button).centerY();
if (eventActionMasked == MotionEvent.ACTION_CANCEL) {
mAppMenu.dismiss();
return true;
} else if (eventActionMasked == MotionEvent.ACTION_UP) {
nativeRecordAppMenuTouchDuration(timeSinceDown);
}
mIsSingleTapCanceled |= timeSinceDown > mTapTimeout;
mIsSingleTapCanceled |= !pointInView(button, event.getX(), event.getY(), mScaledTouchSlop);
if (!mIsSingleTapCanceled && eventActionMasked == MotionEvent.ACTION_UP) {
RecordUserAction.record("MobileUsingMenuBySwButtonTap");
finishDragging();
}
// After this line, drag scrolling is happening.
if (!mDragScrolling.isRunning()) return false;
boolean didPerformClick = false;
int itemAction = ITEM_ACTION_CLEAR_HIGHLIGHT_ALL;
switch (eventActionMasked) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
itemAction = ITEM_ACTION_HIGHLIGHT;
break;
case MotionEvent.ACTION_UP:
itemAction = ITEM_ACTION_PERFORM;
break;
default:
break;
}
didPerformClick = menuItemAction(roundedRawX, roundedRawY, itemAction);
if (eventActionMasked == MotionEvent.ACTION_UP && !didPerformClick) {
RecordUserAction.record("MobileUsingMenuBySwButtonDragging");
mAppMenu.dismiss();
} else if (eventActionMasked == MotionEvent.ACTION_MOVE) {
// Auto scrolling on the top or the bottom of the listView.
if (listView.getHeight() > 0) {
float autoScrollAreaRatio = Math.min(AUTO_SCROLL_AREA_MAX_RATIO,
mItemRowHeight * 1.2f / listView.getHeight());
float normalizedY =
(rawY - getScreenVisibleRect(listView).top) / listView.getHeight();
if (normalizedY < autoScrollAreaRatio) {
// Top
mDragScrollingVelocity = (normalizedY / autoScrollAreaRatio - 1.0f)
* mAutoScrollFullVelocity;
} else if (normalizedY > 1.0f - autoScrollAreaRatio) {
// Bottom
mDragScrollingVelocity = ((normalizedY - 1.0f) / autoScrollAreaRatio + 1.0f)
* mAutoScrollFullVelocity;
} else {
// Middle or not scrollable.
mDragScrollingVelocity = 0.0f;
}
}
}
return true;
}
@Override
public boolean onTouchEvent(MotionEvent me) {
// Convert multi-pointer up/down events to single up/down events to
// deal with the typical multi-pointer behavior of two-thumb typing
final int pointerCount = me.getPointerCount();
final int action = me.getAction();
boolean result = false;
final long now = me.getEventTime();
if (pointerCount != mOldPointerCount) {
if (pointerCount == 1) {
// Send a down event for the latest pointer
MotionEvent down = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN,
me.getX(), me.getY(), me.getMetaState());
result = onModifiedTouchEvent(down, false);
down.recycle();
// If it's an up action, then deliver the up as well.
if (action == MotionEvent.ACTION_UP) {
result = onModifiedTouchEvent(me, true);
}
} else {
// Send an up event for the last pointer
MotionEvent up = MotionEvent.obtain(now, now, MotionEvent.ACTION_UP,
mOldPointerX, mOldPointerY, me.getMetaState());
result = onModifiedTouchEvent(up, true);
up.recycle();
}
} else {
if (pointerCount == 1) {
result = onModifiedTouchEvent(me, false);
mOldPointerX = me.getX();
mOldPointerY = me.getY();
} else {
// Don't do anything when 2 pointers are down and moving.
result = true;
}
}
mOldPointerCount = pointerCount;
return result;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
if (mController.isScrolling())
{
return true;
}
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN)
{
mCheckToIntercept = true;
mDown = MotionEvent.obtain(ev);
return false;
} else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN)
{
// Do not intercept touch once child is in zoom mode
mCheckToIntercept = false;
return false;
} else
{
if (!mCheckToIntercept)
{
return false;
}
if (ev.getEventTime() - ev.getDownTime() > SWIPE_TIME_OUT)
{
return false;
}
int deltaX = (int) (ev.getX() - mDown.getX());
int deltaY = (int) (ev.getY() - mDown.getY());
if (ev.getActionMasked() == MotionEvent.ACTION_MOVE
&& deltaX < mSlop * (-1))
{
// intercept left swipe
if (Math.abs(deltaX) >= Math.abs(deltaY) * 2)
{
return true;
}
}
}
return false;
}
@Override
public boolean handleMoveTouchEvent(MotionEvent event) {
// Switching 'pointers' (e.g. fingers) on-the-fly isn't supported -- abort over-scroll
// smoothly using the default bounce-back animation in this case.
if (mOverScrollStartAttr.mPointerId != event.getPointerId(0)) {
issueStateTransition(mBounceBackState);
return true;
}
final View view = mViewAdapter.getView();
if (!mMoveAttr.init(view, event)) {
// Keep intercepting the touch event as long as we're still over-scrolling...
return true;
}
float deltaOffset = mMoveAttr.mDeltaOffset / (mMoveAttr.mDir == mOverScrollStartAttr.mDir ? mTouchDragRatioFwd : mTouchDragRatioBck);
float newOffset = mMoveAttr.mAbsOffset + deltaOffset;
// If moved in counter direction onto a potential under-scroll state -- don't. Instead, abort
// over-scrolling abruptly, thus returning control to which-ever touch handlers there
// are waiting (e.g. regular scroller handlers).
if ((mOverScrollStartAttr.mDir && !mMoveAttr.mDir && (newOffset <= mOverScrollStartAttr.mAbsOffset)) ||
(!mOverScrollStartAttr.mDir && mMoveAttr.mDir && (newOffset >= mOverScrollStartAttr.mAbsOffset))) {
translateViewAndEvent(view, mOverScrollStartAttr.mDir, mOverScrollStartAttr.mAbsOffset, event);
mUpdateListener.onOverScrollUpdate(ElasticityBounceEffectBase.this, mCurrDragState, 0);
issueStateTransition(mIdleState);
return true;
}
if (view.getParent() != null) {
view.getParent().requestDisallowInterceptTouchEvent(true);
}
long dt = event.getEventTime() - event.getHistoricalEventTime(0);
if (dt > 0) { // Sometimes (though rarely) dt==0 cause originally timing is in nanos, but is presented in millis.
mVelocity = deltaOffset / dt;
}
translateView(view, mOverScrollStartAttr.mDir, newOffset);
mUpdateListener.onOverScrollUpdate(ElasticityBounceEffectBase.this, mCurrDragState, newOffset);
return true;
}