/** * Posts a pointer event to the dispatch queue. * * @param event The event to post. * @param webKitXOffset X offset to apply to events before dispatching them to web kit. * @param webKitYOffset Y offset to apply to events before dispatching them to web kit. * @param webKitScale The scale factor to apply to translated events before dispatching them to * web kit. * @return True if the dispatcher will handle the event, false if the event is unsupported. */ public boolean postPointerEvent( MotionEvent event, int webKitXOffset, int webKitYOffset, float webKitScale) { if (event == null) { throw new IllegalArgumentException("event cannot be null"); } if (DEBUG) { Log.d(TAG, "postPointerEvent: " + event); } final int action = event.getActionMasked(); final int eventType; switch (action) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_CANCEL: eventType = EVENT_TYPE_TOUCH; break; case MotionEvent.ACTION_SCROLL: eventType = EVENT_TYPE_SCROLL; break; case MotionEvent.ACTION_HOVER_ENTER: case MotionEvent.ACTION_HOVER_MOVE: case MotionEvent.ACTION_HOVER_EXIT: eventType = EVENT_TYPE_HOVER; break; default: return false; // currently unsupported event type } synchronized (mLock) { // Ensure that the event is consistent and should be delivered. MotionEvent eventToEnqueue = event; if (eventType == EVENT_TYPE_TOUCH) { eventToEnqueue = mPostTouchStream.update(event); if (eventToEnqueue == null) { if (DEBUG) { Log.d(TAG, "postPointerEvent: dropped event " + event); } unscheduleLongPressLocked(); unscheduleClickLocked(); hideTapCandidateLocked(); return false; } if (action == MotionEvent.ACTION_DOWN && mPostSendTouchEventsToWebKit) { if (mUiCallbacks.shouldInterceptTouchEvent(eventToEnqueue)) { mPostDoNotSendTouchEventsToWebKitUntilNextGesture = true; } else if (mPostDoNotSendTouchEventsToWebKitUntilNextGesture) { // Recover from a previous web kit timeout. mPostDoNotSendTouchEventsToWebKitUntilNextGesture = false; } } } // Copy the event because we need to retain ownership. if (eventToEnqueue == event) { eventToEnqueue = event.copy(); } DispatchEvent d = obtainDispatchEventLocked( eventToEnqueue, eventType, 0, webKitXOffset, webKitYOffset, webKitScale); updateStateTrackersLocked(d, event); enqueueEventLocked(d); } return true; }
@Override public boolean onTouchEvent(MotionEvent event) { if (!isEnabled()) return false; final View parent = (View) getParent(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { // only start tracking when in sweet spot final boolean acceptDrag; final boolean acceptLabel; if (mFollowAxis == VERTICAL) { acceptDrag = event.getX() > getWidth() - (mSweepPadding.right * 8); acceptLabel = mLabelLayout != null ? event.getX() < mLabelLayout.getWidth() : false; } else { acceptDrag = event.getY() > getHeight() - (mSweepPadding.bottom * 8); acceptLabel = mLabelLayout != null ? event.getY() < mLabelLayout.getHeight() : false; } final MotionEvent eventInParent = event.copy(); eventInParent.offsetLocation(getLeft(), getTop()); // ignore event when closer to a neighbor for (ChartSweepView neighbor : mNeighbors) { if (isTouchCloserTo(eventInParent, neighbor)) { return false; } } if (acceptDrag) { if (mFollowAxis == VERTICAL) { mTrackingStart = getTop() - mMargins.top; } else { mTrackingStart = getLeft() - mMargins.left; } mTracking = event.copy(); mTouchMode = MODE_DRAG; // starting drag should activate entire chart if (!parent.isActivated()) { parent.setActivated(true); } return true; } else if (acceptLabel) { mTouchMode = MODE_LABEL; return true; } else { mTouchMode = MODE_NONE; return false; } } case MotionEvent.ACTION_MOVE: { if (mTouchMode == MODE_LABEL) { return true; } getParent().requestDisallowInterceptTouchEvent(true); // content area of parent final Rect parentContent = getParentContentRect(); final Rect clampRect = computeClampRect(parentContent); if (clampRect.isEmpty()) return true; long value; if (mFollowAxis == VERTICAL) { final float currentTargetY = getTop() - mMargins.top; final float requestedTargetY = mTrackingStart + (event.getRawY() - mTracking.getRawY()); final float clampedTargetY = MathUtils.constrain(requestedTargetY, clampRect.top, clampRect.bottom); setTranslationY(clampedTargetY - currentTargetY); value = mAxis.convertToValue(clampedTargetY - parentContent.top); } else { final float currentTargetX = getLeft() - mMargins.left; final float requestedTargetX = mTrackingStart + (event.getRawX() - mTracking.getRawX()); final float clampedTargetX = MathUtils.constrain(requestedTargetX, clampRect.left, clampRect.right); setTranslationX(clampedTargetX - currentTargetX); value = mAxis.convertToValue(clampedTargetX - parentContent.left); } // round value from drag to nearest increment value -= value % mDragInterval; setValue(value); dispatchOnSweep(false); return true; } case MotionEvent.ACTION_UP: { if (mTouchMode == MODE_LABEL) { performClick(); } else if (mTouchMode == MODE_DRAG) { mTrackingStart = 0; mTracking = null; mValue = mLabelValue; dispatchOnSweep(true); setTranslationX(0); setTranslationY(0); requestLayout(); } mTouchMode = MODE_NONE; return true; } default: { return false; } } }