/** * Duplicate touch events to child views. We want to dispatch a down motion event and the move * events to child views, but calling dispatchTouchEvent() causes StackOverflowError. Therefore we * do it manually. * * @param ev motion event to be passed to children * @param pendingEvents pending events like ACTION_DOWN. This will be passed to the children * before ev */ private void duplicateTouchEventForChildren(MotionEvent ev, MotionEvent... pendingEvents) { if (ev == null) { return; } for (int i = getChildCount() - 1; 0 <= i; i--) { View childView = getChildAt(i); if (childView != null) { Rect childRect = new Rect(); childView.getHitRect(childRect); MotionEvent event = MotionEvent.obtainNoHistory(ev); if (!childRect.contains((int) event.getX(), (int) event.getY())) { continue; } float offsetX = -childView.getLeft(); float offsetY = -childView.getTop(); boolean consumed = false; if (pendingEvents != null) { for (MotionEvent pe : pendingEvents) { if (pe != null) { MotionEvent peAdjusted = MotionEvent.obtainNoHistory(pe); peAdjusted.offsetLocation(offsetX, offsetY); consumed |= childView.dispatchTouchEvent(peAdjusted); } } } event.offsetLocation(offsetX, offsetY); consumed |= childView.dispatchTouchEvent(event); if (consumed) { break; } } } }
@StressTest @UiThreadTest public void testRandomTouch() { MemoryLogger memoryLogger = new MemoryLogger("testRandomTouch", 100); viewManager.setKeyboardLayout(KeyboardLayout.TWELVE_KEYS); final int actions = 500; final Random random = new Random(); Rect rect = getViewRect(); memoryLogger.logMemory("start"); for (int i = 0; i < actions; i++) { final int x = rect.left + random.nextInt(rect.width()); final int y = rect.top + random.nextInt(rect.height()); inputView.dispatchTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, x, y, 0)); inputView.dispatchTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, x, y, 0)); // updateRequest sends asynchronous message to server. So we need to wait a moment // for server processing. sleep(200); memoryLogger.logMemoryInterval(); } memoryLogger.logMemory("start"); }
@Override public boolean dispatchTouchEvent(MotionEvent event) { if (!onFilterTouchEventForSecurity(event)) return false; int action = event.getAction(); double dx = event.getX() - mCenterX; double dy = mCenterY - event.getY(); double radius = Math.sqrt(dx * dx + dy * dy); // Check if the event should be dispatched to the shutter button. if (radius <= mShutterButtonRadius) { if (mIndicatorControlWheel.getVisibility() == View.VISIBLE) { mIndicatorControlWheel.onTouchOutBound(); } if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP) { return mShutterButton.dispatchTouchEvent(event); } return false; } if (mShutterButton.isPressed()) { // Send cancel to the shutter button if it was pressed. event.setAction(MotionEvent.ACTION_CANCEL); mShutterButton.dispatchTouchEvent(event); return true; } return mIndicatorControlWheel.dispatchTouchEvent(event); }
@Override public boolean dispatchTouchEvent(MotionEvent e) { float x = e.getX(); float y = e.getY(); if (mDispatchTouchEventToHeaderView) { boolean result = mHeaderView != null && mHeaderView.dispatchTouchEvent(e); if (e.getAction() == MotionEvent.ACTION_CANCEL || e.getAction() == MotionEvent.ACTION_UP) { mDispatchTouchEventToHeaderView = false; } return result; } if (mHeaderView != null && x >= 0 && x <= mHeaderView.getMeasuredWidth() && y >= 0 && y <= (mHeaderView.getMeasuredHeight() - mCurHeaderViewPushUpDistance) && e.getAction() == MotionEvent.ACTION_DOWN && mHeaderView.getVisibility() == View.VISIBLE && mHeaderView.dispatchTouchEvent(e)) { mDispatchTouchEventToHeaderView = true; return true; } else { return super.dispatchTouchEvent(e); } }
@Override public boolean dispatchTouchEvent(MotionEvent ev) { final float x = ev.getX(); final float y = ev.getY(); final int action = ev.getAction(); if (action == MotionEvent.ACTION_DOWN && mTouchTarget == null && mPinnedSection != null && isPinnedViewTouched(mPinnedSection.view, x, y)) { // create touch target // user touched pinned view mTouchTarget = mPinnedSection.view; mTouchPoint.x = x; mTouchPoint.y = y; // copy down event for eventually be used later mDownEvent = MotionEvent.obtain(ev); } if (mTouchTarget != null) { if (isPinnedViewTouched(mTouchTarget, x, y)) { // forward event to pinned view mTouchTarget.dispatchTouchEvent(ev); } if (action == MotionEvent.ACTION_UP) { // perform onClick on pinned view super.dispatchTouchEvent(ev); performPinnedItemClick(); clearTouchTarget(); } else if (action == MotionEvent.ACTION_CANCEL) { // cancel clearTouchTarget(); } else if (action == MotionEvent.ACTION_MOVE) { if (Math.abs(y - mTouchPoint.y) > mTouchSlop) { // cancel sequence on touch target MotionEvent event = MotionEvent.obtain(ev); event.setAction(MotionEvent.ACTION_CANCEL); mTouchTarget.dispatchTouchEvent(event); event.recycle(); // provide correct sequence to super class for further handling super.dispatchTouchEvent(mDownEvent); super.dispatchTouchEvent(ev); clearTouchTarget(); } } return true; } // call super if this was not our pinned view return super.dispatchTouchEvent(ev); }
/** * Override method to dispatch touch event to the dragged view. * * @param ev captured. * @return true if the touch event is realized over the drag or second view. */ @Override public boolean onTouchEvent(MotionEvent ev) { viewDragHelper.processTouchEvent(ev); if (isClosed()) { return false; } boolean isDragViewHit = isViewHit(dragView, (int) ev.getX(), (int) ev.getY()); boolean isSecondViewHit = isViewHit(secondView, (int) ev.getX(), (int) ev.getY()); if (isMaximized()) { dragView.dispatchTouchEvent(ev); } else { dragView.dispatchTouchEvent(cloneMotionEventWithAction(ev, MotionEvent.ACTION_CANCEL)); } return isDragViewHit || isSecondViewHit; }
public boolean onTouchEvent(MotionEvent event) { boolean eventCatch = false; long time = event.getEventTime(); eventCatch = evaluateTouch(event); if (!eventCatch) { Vector<ARSphericalView> arViewReverse = new Vector<ARSphericalView>(getArViews()); Collections.sort(arViewReverse); Iterator<ARSphericalView> it = arViewReverse.iterator(); View v; while (it.hasNext() && !eventCatch) { v = it.next(); eventCatch = v.dispatchTouchEvent(event); if (!poiMove) poiMove = ((MagnitudePOI) v).isShifted(); } } if (!eventCatch) { if (event.getAction() == MotionEvent.ACTION_DOWN) { timeOfStart = time; inClick = true; } else if (inClick && event.getAction() == MotionEvent.ACTION_UP && (time - timeOfStart) > 1000) { LaunchAction(); inClick = false; } } return true; }
public boolean dispatchTouchEvent(MotionEvent paramMotionEvent) { float f1 = paramMotionEvent.getRawX(); float f2 = paramMotionEvent.getRawY(); if ((this.f == null) && (this.a != null) && (this.a.getVisibility() == 0) && (this.b != null)) { this.b.getLocationOnScreen(this.g); if ((f1 >= this.g[0]) && (f1 < this.g[0] + this.b.getWidth()) && (f2 >= this.g[1]) && (f2 < this.g[1] + this.b.getHeight())) { this.f = this.a; } } if ((this.f == null) && (this.a != null) && (this.a.getVisibility() == 0)) { if ((this.d == null) || (this.d.getVisibility() != 0)) { break label269; } this.d.getLocationOnScreen(this.g); if (f2 >= this.g[1]) { this.f = this.a; } if (f2 >= this.g[1]) { this.f = this.a; } } int i = paramMotionEvent.getAction(); if (this.f != null) { localView = this.f; if (paramMotionEvent.getAction() == 3) { localView.dispatchTouchEvent(paramMotionEvent); if ((i == 3) || (i == 1)) { this.f = null; } } } label269: while (this.e == null) { for (;;) { View localView; return true; if ((this.c != null) && (this.c.getVisibility() == 0)) { this.c.getLocationOnScreen(this.g); break; } this.g[0] = 2147483647; this.g[1] = 2147483647; break; MotionEvent localMotionEvent = MotionEvent.obtain(paramMotionEvent); localMotionEvent.offsetLocation(getScrollX() - localView.getLeft(), getScrollY() - localView.getTop()); localView.dispatchTouchEvent(localMotionEvent); localMotionEvent.recycle(); } } this.e.a(i); return true; }
@Test public void dispatchTouchEvent_sendsMotionEventToOnTouchEvent() throws Exception { TouchableView touchableView = new TouchableView(null); MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 12f, 34f, 0); touchableView.dispatchTouchEvent(event); assertThat(touchableView.event, sameInstance(event)); view.dispatchTouchEvent(event); assertThat(shadowOf(view).getLastTouchEvent(), sameInstance(event)); }
public boolean onTouchEvent(MotionEvent motionevent) { if (isTouchInPinnedHeader(motionevent)) { motionevent.setLocation( motionevent.getX(), motionevent.getY() - (float) mPinnedHeaderOffset - (float) mNavBottom); return mPinnedHeaderView.dispatchTouchEvent(motionevent); } else { return super.onTouchEvent(motionevent); } }
@Override public boolean dispatchTouchEvent(MotionEvent ev) { if (((!mEnabled || !mInterceptTouch) && mMode == MODE_READY) || mAlwaysOpened) { return super.dispatchTouchEvent(ev); } if (mMode != MODE_FINISHED) { onTouchEvent(ev); if (mMode != MODE_SLIDE) { super.dispatchTouchEvent(ev); } else { MotionEvent cancelEvent = MotionEvent.obtain(ev); cancelEvent.setAction(MotionEvent.ACTION_CANCEL); super.dispatchTouchEvent(cancelEvent); cancelEvent.recycle(); } return true; } else { final int action = ev.getAction(); Rect rect = new Rect(); View menu = getChildAt(0); menu.getHitRect(rect); if (!rect.contains((int) ev.getX(), (int) ev.getY())) { if (action == MotionEvent.ACTION_UP && mCloseOnRelease && !mDispatchWhenOpened) { close(); mCloseOnRelease = false; } else { if (action == MotionEvent.ACTION_DOWN && !mDispatchWhenOpened) { mCloseOnRelease = true; } onTouchEvent(ev); } if (mDispatchWhenOpened) { super.dispatchTouchEvent(ev); } return true; } else { onTouchEvent(ev); ev.offsetLocation(-menu.getLeft(), -menu.getTop()); menu.dispatchTouchEvent(ev); return true; } } }
@Test public void dispatchTouchEvent_listensToFalseFromListener() throws Exception { view.setOnTouchListener( new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { return false; } }); MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 12f, 34f, 0); view.dispatchTouchEvent(event); assertThat(shadowOf(view).getLastTouchEvent(), sameInstance(event)); }
@Override public boolean dispatchTouchEvent(MotionEvent ev) { int action = ev.getAction() & MotionEvent.ACTION_MASK; if (action == MotionEvent.ACTION_DOWN) { mDownY = ev.getY(); mHeaderOwnsTouch = mHeader != null && mDownY <= mHeader.getHeight() + mHeaderOffset; } boolean handled; if (mHeaderOwnsTouch) { if (mHeader != null && Math.abs(mDownY - ev.getY()) <= mTouchSlop) { handled = mHeader.dispatchTouchEvent(ev); } else { if (mHeader != null) { MotionEvent cancelEvent = MotionEvent.obtain(ev); cancelEvent.setAction(MotionEvent.ACTION_CANCEL); mHeader.dispatchTouchEvent(cancelEvent); cancelEvent.recycle(); } MotionEvent downEvent = MotionEvent.obtain( ev.getDownTime(), ev.getEventTime(), ev.getAction(), ev.getX(), mDownY, ev.getMetaState()); downEvent.setAction(MotionEvent.ACTION_DOWN); handled = mList.dispatchTouchEvent(downEvent); downEvent.recycle(); mHeaderOwnsTouch = false; } } else { handled = mList.dispatchTouchEvent(ev); } return handled; }
@Override public boolean onTouchEvent(MotionEvent ev) { boolean result = super.onTouchEvent(ev); mTempRect.set(0, 0, 0, 0); for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); if (child.getVisibility() == View.VISIBLE) { offsetRectIntoDescendantCoords(child, mTempRect); ev.offsetLocation(mTempRect.left, mTempRect.top); result = child.dispatchTouchEvent(ev) || result; ev.offsetLocation(-mTempRect.left, -mTempRect.top); } } return result; }
@Override public boolean dispatchTouchEvent(MotionEvent ev) { boolean ret = false; // Make sure that the infoWindow is shown and we have all the needed references if (marker != null && marker.isInfoWindowShown() && map != null && infoWindow != null) { // Get a marker position on the screen Point point = map.getProjection().toScreenLocation(marker.getPosition()); // Make a copy of the MotionEvent and adjust it's location // so it is relative to the infoWindow left top corner MotionEvent copyEv = MotionEvent.obtain(ev); copyEv.offsetLocation( -point.x + (infoWindow.getWidth() / 2), -point.y + infoWindow.getHeight() + bottomOffsetPixels); // Dispatch the adjusted MotionEvent to the infoWindow ret = infoWindow.dispatchTouchEvent(copyEv); } // If the infoWindow consumed the touch event, then just return true. // Otherwise pass this event to the super class and return it's result return ret || super.dispatchTouchEvent(ev); }
private void injectMotionEvent(int viewIndex, MotionEvent event, int action) { View v = getChildAt(viewIndex); event.setAction(action); v.dispatchTouchEvent(event); }
@Override public boolean onTouchEvent(MotionEvent ev) { final int action = ev.getAction(); boolean wasHeaderChildBeingPressed = mHeaderChildBeingPressed; if (mHeaderChildBeingPressed) { final View tempHeader = getHeaderAt(mMotionHeaderPosition); final View headerHolder = mMotionHeaderPosition == MATCHED_STICKIED_HEADER ? tempHeader : getChildAt(mMotionHeaderPosition); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { mHeaderChildBeingPressed = false; } if (tempHeader != null) { tempHeader.dispatchTouchEvent(transformEvent(ev, mMotionHeaderPosition)); tempHeader.invalidate(); tempHeader.postDelayed( new Runnable() { public void run() { invalidate( 0, headerHolder.getTop(), getWidth(), headerHolder.getTop() + headerHolder.getHeight()); } }, ViewConfiguration.getPressedStateDuration()); invalidate( 0, headerHolder.getTop(), getWidth(), headerHolder.getTop() + headerHolder.getHeight()); } } switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: if (mPendingCheckForTap == null) { mPendingCheckForTap = new CheckForHeaderTap(); } postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); final int y = (int) ev.getY(); mMotionY = y; mMotionHeaderPosition = findMotionHeader(y); if (mMotionHeaderPosition == NO_MATCHED_HEADER || mScrollState == SCROLL_STATE_FLING) { // Don't consume the event and pass it to super because we // can't handle it yet. break; } else { View tempHeader = getHeaderAt(mMotionHeaderPosition); if (tempHeader != null) { if (tempHeader.dispatchTouchEvent(transformEvent(ev, mMotionHeaderPosition))) { mHeaderChildBeingPressed = true; tempHeader.setPressed(true); } tempHeader.invalidate(); if (mMotionHeaderPosition != MATCHED_STICKIED_HEADER) { tempHeader = getChildAt(mMotionHeaderPosition); } invalidate( 0, tempHeader.getTop(), getWidth(), tempHeader.getTop() + tempHeader.getHeight()); } } mTouchMode = TOUCH_MODE_DOWN; return true; case MotionEvent.ACTION_MOVE: if (mMotionHeaderPosition != NO_MATCHED_HEADER && Math.abs(ev.getY() - mMotionY) > mTouchSlop) { // Detected scroll initiation so cancel touch completion on // header. mTouchMode = TOUCH_MODE_REST; // if (!mHeaderChildBeingPressed) { final View header = getHeaderAt(mMotionHeaderPosition); if (header != null) { header.setPressed(false); header.invalidate(); } final Handler handler = getHandler(); if (handler != null) { handler.removeCallbacks(mPendingCheckForLongPress); } mMotionHeaderPosition = NO_MATCHED_HEADER; // } } break; case MotionEvent.ACTION_UP: if (mTouchMode == TOUCH_MODE_FINISHED_LONG_PRESS) { mTouchMode = TOUCH_MODE_REST; return true; } if (mTouchMode == TOUCH_MODE_REST || mMotionHeaderPosition == NO_MATCHED_HEADER) { break; } final View header = getHeaderAt(mMotionHeaderPosition); if (!wasHeaderChildBeingPressed) { if (header != null) { if (mTouchMode != TOUCH_MODE_DOWN) { header.setPressed(false); } if (mPerformHeaderClick == null) { mPerformHeaderClick = new PerformHeaderClick(); } final PerformHeaderClick performHeaderClick = mPerformHeaderClick; performHeaderClick.mClickMotionPosition = mMotionHeaderPosition; performHeaderClick.rememberWindowAttachCount(); if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) { final Handler handler = getHandler(); if (handler != null) { handler.removeCallbacks( mTouchMode == TOUCH_MODE_DOWN ? mPendingCheckForTap : mPendingCheckForLongPress); } if (!mDataChanged) { /* * Got here so must be a tap. The long press * would have triggered on the callback handler. */ mTouchMode = TOUCH_MODE_TAP; header.setPressed(true); setPressed(true); if (mTouchModeReset != null) { removeCallbacks(mTouchModeReset); } mTouchModeReset = new Runnable() { @Override public void run() { mMotionHeaderPosition = NO_MATCHED_HEADER; mTouchModeReset = null; mTouchMode = TOUCH_MODE_REST; header.setPressed(false); setPressed(false); header.invalidate(); invalidate(0, header.getTop(), getWidth(), header.getHeight()); if (!mDataChanged) { performHeaderClick.run(); } } }; postDelayed(mTouchModeReset, ViewConfiguration.getPressedStateDuration()); } else { mTouchMode = TOUCH_MODE_REST; } } else if (!mDataChanged) { performHeaderClick.run(); } } } mTouchMode = TOUCH_MODE_REST; return true; } return super.onTouchEvent(ev); }
// Pass all touches along to the handle, allowing the user to drag the panel closed from its // interior @Override public boolean onTouchEvent(MotionEvent event) { return mHandleView.dispatchTouchEvent(event); }