void SetContext(MotionEvent curr) { if (mCurrEvent != null) { mCurrEvent.Recycle(); } mCurrEvent = MotionEvent.Obtain(curr); mCurrLen = -1; mPrevLen = -1; mScaleFactor = -1; MotionEvent prev = mPrevEvent; int prevIndex0 = prev.FindPointerIndex(mActiveId0); int prevIndex1 = prev.FindPointerIndex(mActiveId1); int currIndex0 = curr.FindPointerIndex(mActiveId0); int currIndex1 = curr.FindPointerIndex(mActiveId1); if (prevIndex0 < 0 || prevIndex1 < 0 || currIndex0 < 0 || currIndex1 < 0) { mInvalidGesture = true; if (mGestureInProgress) { mListener.OnScaleEnd(this); } return; } float px0 = prev.GetX(prevIndex0); float py0 = prev.GetY(prevIndex0); float px1 = prev.GetX(prevIndex1); float py1 = prev.GetY(prevIndex1); float cx0 = curr.GetX(currIndex0); float cy0 = curr.GetY(currIndex0); float cx1 = curr.GetX(currIndex1); float cy1 = curr.GetY(currIndex1); float pvx = px1 - px0; float pvy = py1 - py0; float cvx = cx1 - cx0; float cvy = cy1 - cy0; mPrevFingerDiffX = pvx; mPrevFingerDiffY = pvy; mCurrFingerDiffX = cvx; mCurrFingerDiffY = cvy; mFocusX = cx0 + cvx * 0.5f; mFocusY = cy0 + cvy * 0.5f; mTimeDelta = curr.EventTime - prev.EventTime; mCurrPressure = curr.GetPressure(currIndex0) + curr.GetPressure(currIndex1); mPrevPressure = prev.GetPressure(prevIndex0) + prev.GetPressure(prevIndex1); }
public override bool DispatchTouchEvent(MotionEvent ev) { float x = ev.GetX(); float y = ev.GetY(); MotionEventActions action = ev.Action; if (action == MotionEventActions.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 == MotionEventActions.Up) // perform onClick on pinned view { base.DispatchTouchEvent(ev); performPinnedItemClick(); clearTouchTarget(); } else if (action == MotionEventActions.Cancel) // cancel { clearTouchTarget(); } else if (action == MotionEventActions.Move) { if (Math.Abs(y - mTouchPoint.Y) > mTouchSlop) { // cancel sequence on touch target MotionEvent events = MotionEvent.Obtain(ev); events.Action = MotionEventActions.Cancel; mTouchTarget.DispatchTouchEvent(events); events.Recycle(); // provide correct sequence to super class for further handling base.DispatchTouchEvent(mDownEvent); base.DispatchTouchEvent(ev); clearTouchTarget(); } } return(true); } return(base.DispatchTouchEvent(ev)); }
private void clearTouchTarget() { mTouchTarget = null; if (mDownEvent != null) { mDownEvent.Recycle(); mDownEvent = null; } }
private bool handleMoveEvent(View view, MotionEvent motionEvent) { if (mVelocityTracker == null || mCurrentView == null) { return(false); } mVelocityTracker.AddMovement(motionEvent); float deltaX = motionEvent.GetX() - mDownX; float deltaY = motionEvent.GetY() - mDownY; if (Math.Abs(deltaX) > mSlop && Math.Abs(deltaX) > Math.Abs(deltaY)) { if (!mSwiping) { mActiveSwipeCount++; onStartSwipe(mCurrentView, mCurrentPosition); } mSwiping = true; mListViewWrapper.getListView().RequestDisallowInterceptTouchEvent(true); /* Cancel ListView's touch (un-highlighting the item) */ if (view != null) { MotionEvent cancelEvent = MotionEvent.Obtain(motionEvent); int mode = (int)MotionEventActions.Cancel | (motionEvent.ActionIndex << (int)MotionEventActions.PointerIndexShift); cancelEvent.Action = (MotionEventActions)mode; view.OnTouchEvent(cancelEvent); cancelEvent.Recycle(); } } if (mSwiping) { if (mCanDismissCurrent) { //ViewHelper.setTranslationX(mSwipingView, deltaX); mSwipingView.TranslationX = deltaX; //ViewHelper.setAlpha(mSwipingView, Math.Max(mMinimumAlpha, Math.Min(1, 1 - 2 * Math.Abs(deltaX) / mViewWidth))); mSwipingView.Alpha = Math.Max(mMinimumAlpha, Math.Min(1, 1 - 2 * Math.Abs(deltaX) / mViewWidth)); } else { //ViewHelper.setTranslationX(mSwipingView, deltaX * 0.1f); mSwipingView.TranslationX = deltaX * 0.1f; } return(true); } return(false); }
public override bool DispatchTouchEvent(MotionEvent ev) { if (ev.Action == MotionEventActions.Down) { m_DownY = ev.GetY(); m_HeaderOwnsTouch = m_Header != null && m_DownY <= m_Header.Height + m_HeaderOffset; } bool handled = false; if (m_HeaderOwnsTouch) { if (m_Header != null && Math.Abs(m_DownY - ev.GetY()) <= m_TouchSlop) { handled = m_Header.DispatchTouchEvent(ev); } else { if (m_Header != null) { MotionEvent cancelEvent = MotionEvent.Obtain(ev); cancelEvent.Action = MotionEventActions.Cancel; m_Header.DispatchTouchEvent(cancelEvent); cancelEvent.Recycle(); } MotionEvent downEvent = MotionEvent.Obtain(ev.DownTime, ev.EventTime, ev.Action, ev.GetX(), m_DownY, ev.MetaState); downEvent.Action = MotionEventActions.Down; handled = base.DispatchTouchEvent(downEvent); downEvent.Recycle(); m_HeaderOwnsTouch = false; } } else { handled = base.DispatchTouchEvent(ev); } return(handled); }
public bool OnTouchEvent(MotionEvent evt) { var action = evt.ActionMasked; if (action == MotionEventActions.Down) { Reset(); // Start fresh } bool handled = true; if (mInvalidGesture) { handled = false; } else if (!mGestureInProgress) { switch (action) { case MotionEventActions.Down: { mActiveId0 = evt.GetPointerId(0); mActive0MostRecent = true; } break; case MotionEventActions.Up: Reset(); break; case MotionEventActions.PointerDown: { // We have a new multi-finger gesture if (mPrevEvent != null) { mPrevEvent.Recycle(); } mPrevEvent = MotionEvent.Obtain(evt); mTimeDelta = 0; int index1 = evt.ActionIndex; int index0 = evt.FindPointerIndex(mActiveId0); mActiveId1 = evt.GetPointerId(index1); if (index0 < 0 || index0 == index1) { // Probably someone sending us a broken evt stream. index0 = FindNewActiveIndex(evt, mActiveId1, -1); mActiveId0 = evt.GetPointerId(index0); } mActive0MostRecent = false; SetContext(evt); mGestureInProgress = mListener.OnScaleBegin(this); break; } } } else { // Transform gesture in progress - attempt to handle it switch (action) { case MotionEventActions.Down: { // End the old gesture and begin a new one with the most recent two fingers. mListener.OnScaleEnd(this); int oldActive0 = mActiveId0; int oldActive1 = mActiveId1; Reset(); mPrevEvent = MotionEvent.Obtain(evt); mActiveId0 = mActive0MostRecent ? oldActive0 : oldActive1; mActiveId1 = evt.GetPointerId(evt.ActionIndex); mActive0MostRecent = false; int index0 = evt.FindPointerIndex(mActiveId0); if (index0 < 0 || mActiveId0 == mActiveId1) { index0 = FindNewActiveIndex(evt, mActiveId1, -1); mActiveId0 = evt.GetPointerId(index0); } SetContext(evt); mGestureInProgress = mListener.OnScaleBegin(this); } break; case MotionEventActions.PointerUp: { int pointerCount = evt.PointerCount; int actionIndex = evt.ActionIndex; int actionId = evt.GetPointerId(actionIndex); bool gestureEnded = false; if (pointerCount > 2) { if (actionId == mActiveId0) { int newIndex = FindNewActiveIndex(evt, mActiveId1, actionIndex); if (newIndex >= 0) { mListener.OnScaleEnd(this); mActiveId0 = evt.GetPointerId(newIndex); mActive0MostRecent = true; mPrevEvent = MotionEvent.Obtain(evt); SetContext(evt); mGestureInProgress = mListener.OnScaleBegin(this); } else { gestureEnded = true; } } else if (actionId == mActiveId1) { int newIndex = FindNewActiveIndex(evt, mActiveId0, actionIndex); if (newIndex >= 0) { mListener.OnScaleEnd(this); mActiveId1 = evt.GetPointerId(newIndex); mActive0MostRecent = false; mPrevEvent = MotionEvent.Obtain(evt); SetContext(evt); mGestureInProgress = mListener.OnScaleBegin(this); } else { gestureEnded = true; } } mPrevEvent.Recycle(); mPrevEvent = MotionEvent.Obtain(evt); SetContext(evt); } else { gestureEnded = true; } if (gestureEnded) { // Gesture ended SetContext(evt); // Set focus point to the remaining finger int activeId = actionId == mActiveId0 ? mActiveId1 : mActiveId0; int index = evt.FindPointerIndex(activeId); mFocusX = evt.GetX(index); mFocusY = evt.GetY(index); mListener.OnScaleEnd(this); Reset(); mActiveId0 = activeId; mActive0MostRecent = true; } } break; case MotionEventActions.Cancel: mListener.OnScaleEnd(this); Reset(); break; case MotionEventActions.Up: Reset(); break; case MotionEventActions.Move: { SetContext(evt); // Only accept the evt if our relative pressure is within // a certain limit - this can help filter shaky data as a // finger is lifted. if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) { bool updatePrevious = mListener.OnScale(this); if (updatePrevious) { mPrevEvent.Recycle(); mPrevEvent = MotionEvent.Obtain(evt); } } } break; } } return(handled); }
public bool OnTouch(View view, MotionEvent motionEvent) { if (mViewWidth < 2) { mViewWidth = mListView.Width; } switch (motionEvent.ActionMasked) { case MotionEventActions.Down: if (mPaused) { return(false); } // TODO: ensure this is a finger, and set a flag // Find the child view that was touched (perform a hit test) Rect rect = new Rect(); int childCount = mListView.ChildCount; int[] listViewCoords = new int[2]; mListView.GetLocationOnScreen(listViewCoords); int x = (int)motionEvent.RawX - listViewCoords [0]; int y = (int)motionEvent.RawY - listViewCoords [1]; View child; for (int i = 0; i < childCount; i++) { child = mListView.GetChildAt(i); child.GetHitRect(rect); if (rect.Contains(x, y)) { mDownView = child; break; } } if (mDownView != null) { mDownX = motionEvent.RawX; mDownY = motionEvent.RawY; mDownPosition = mListView.GetPositionForView(mDownView); if (mCallbacks.canDismiss(mDownPosition)) { mVelocityTracker = VelocityTracker.Obtain(); mVelocityTracker.AddMovement(motionEvent); } else { mDownView = null; } } return(false); case MotionEventActions.Cancel: { if (mVelocityTracker == null) { break; } if (mDownView != null && mSwiping) { // cancel mDownView.Animate() .TranslationX(0) .Alpha(1) .SetDuration(mAnimationTime) .SetListener(null); } mVelocityTracker.Recycle(); mVelocityTracker = null; mDownX = 0; mDownY = 0; mDownView = null; mDownPosition = ListView.InvalidPosition; mSwiping = false; break; } case MotionEventActions.Up: { if (mVelocityTracker == null) { break; } float deltaX = motionEvent.RawX - mDownX; mVelocityTracker.AddMovement(motionEvent); mVelocityTracker.ComputeCurrentVelocity(1000); float velocityX = mVelocityTracker.XVelocity; float absVelocityX = Math.Abs(velocityX); float absVelocityY = Math.Abs(mVelocityTracker.YVelocity); bool dismiss = false; bool dismissRight = false; if (Math.Abs(deltaX) > mViewWidth / 2) { dismiss = true; dismissRight = deltaX > 0; } else if (mMinFlingVelocity <= absVelocityX && absVelocityX <= mMaxFlingVelocity && absVelocityY < absVelocityX && mSwiping) { // dismiss only if flinging in the same direction as dragging dismiss = (velocityX < 0) == (deltaX < 0); dismissRight = mVelocityTracker.XVelocity > 0; } if (dismiss && mDownPosition != ListView.InvalidPosition) { // dismiss View downView = mDownView; // mDownView gets null'd before animation ends int downPosition = mDownPosition; ++mDismissAnimationRefCount; var anim = mDownView.Animate() .TranslationX(dismissRight ? mViewWidth : -mViewWidth) .Alpha(0) .SetDuration(mAnimationTime) .SetListener(new DownAnimatorListenerAdapter(this, downView, downPosition)); } else { // cancel mDownView.Animate() .TranslationX(0) .Alpha(1) .SetDuration(mAnimationTime) .SetListener(null); } mVelocityTracker.Recycle(); mVelocityTracker = null; mDownX = 0; mDownY = 0; mDownView = null; mDownPosition = ListView.InvalidPosition; mSwiping = false; break; } case MotionEventActions.Move: { if (mVelocityTracker == null || mPaused) { break; } mVelocityTracker.AddMovement(motionEvent); float deltaX = motionEvent.RawX - mDownX; float deltaY = motionEvent.RawY - mDownY; if (Math.Abs(deltaX) > mSlop && Math.Abs(deltaY) < Math.Abs(deltaX) / 2) { mSwiping = true; mSwipingSlop = (deltaX > 0 ? mSlop : -mSlop); mListView.RequestDisallowInterceptTouchEvent(true); // Cancel ListView's touch (un-highlighting the item) MotionEvent cancelEvent = MotionEvent.Obtain(motionEvent); cancelEvent.Action = (Android.Views.MotionEventActions)((int)MotionEventActions.Cancel | ((int)motionEvent.ActionIndex << (int)MotionEventActions.PointerIndexShift)); mListView.OnTouchEvent(cancelEvent); cancelEvent.Recycle(); } if (mSwiping) { mDownView.TranslationX = deltaX - mSwipingSlop; mDownView.Alpha = Math.Max(0f, Math.Min(1f, 1f - 2f * Math.Abs(deltaX) / mViewWidth)); return(true); } break; } } return(false); }
public bool OnTouchEvent(View view, MotionEvent Event) { try { var action = Event.ActionMasked; if (action == MotionEventActions.Down) { Reset(); // Start fresh } bool handled = true; if (MInvalidGesture) { handled = false; } else if (!MGestureInProgress) { switch (action) { case MotionEventActions.Down: { MActiveId0 = Event.GetPointerId(0); MActive0MostRecent = true; } break; case MotionEventActions.Up: Reset(); break; case MotionEventActions.PointerDown: { // We have a new multi-finger gesture if (MPrevEvent != null) { MPrevEvent.Recycle(); } MPrevEvent = MotionEvent.Obtain(Event); MTimeDelta = 0; int index1 = Event.ActionIndex; int index0 = Event.FindPointerIndex(MActiveId0); MActiveId1 = Event.GetPointerId(index1); if (index0 < 0 || index0 == index1) { // Probably someone sending us a broken Event stream. index0 = FindNewActiveIndex(Event, MActiveId1, -1); MActiveId0 = Event.GetPointerId(index0); } MActive0MostRecent = false; SetContext(view, Event); MGestureInProgress = MListener.OnScaleBegin(view, this); break; } } } else { // Transform gesture in progress - attempt to handle it switch (action) { case MotionEventActions.PointerDown: { // End the old gesture and begin a new one with the most recent two fingers. MListener.OnScaleEnd(view, this); int oldActive0 = MActiveId0; int oldActive1 = MActiveId1; Reset(); MPrevEvent = MotionEvent.Obtain(Event); MActiveId0 = MActive0MostRecent ? oldActive0 : oldActive1; MActiveId1 = Event.GetPointerId(Event.ActionIndex); MActive0MostRecent = false; int index0 = Event.FindPointerIndex(MActiveId0); if (index0 < 0 || MActiveId0 == MActiveId1) { // Probably someone sending us a broken Event stream. index0 = FindNewActiveIndex(Event, MActiveId1, -1); MActiveId0 = Event.GetPointerId(index0); } SetContext(view, Event); MGestureInProgress = MListener.OnScaleBegin(view, this); } break; case MotionEventActions.PointerUp: { int pointerCount = Event.PointerCount; int actionIndex = Event.ActionIndex; int actionId = Event.GetPointerId(actionIndex); bool gestureEnded = false; if (pointerCount > 2) { if (actionId == MActiveId0) { int newIndex = FindNewActiveIndex(Event, MActiveId1, actionIndex); if (newIndex >= 0) { MListener.OnScaleEnd(view, this); MActiveId0 = Event.GetPointerId(newIndex); MActive0MostRecent = true; MPrevEvent = MotionEvent.Obtain(Event); SetContext(view, Event); MGestureInProgress = MListener.OnScaleBegin(view, this); } else { gestureEnded = true; } } else if (actionId == MActiveId1) { int newIndex = FindNewActiveIndex(Event, MActiveId0, actionIndex); if (newIndex >= 0) { MListener.OnScaleEnd(view, this); MActiveId1 = Event.GetPointerId(newIndex); MActive0MostRecent = false; MPrevEvent = MotionEvent.Obtain(Event); SetContext(view, Event); MGestureInProgress = MListener.OnScaleBegin(view, this); } else { gestureEnded = true; } } MPrevEvent.Recycle(); MPrevEvent = MotionEvent.Obtain(Event); SetContext(view, Event); } else { gestureEnded = true; } if (gestureEnded) { // Gesture ended SetContext(view, Event); // Set focus point to the remaining finger int activeId = actionId == MActiveId0 ? MActiveId1 : MActiveId0; int index = Event.FindPointerIndex(activeId); MFocusX = Event.GetX(index); MFocusY = Event.GetY(index); MListener.OnScaleEnd(view, this); Reset(); MActiveId0 = activeId; MActive0MostRecent = true; } } break; case MotionEventActions.Cancel: MListener.OnScaleEnd(view, this); Reset(); break; case MotionEventActions.Up: Reset(); break; case MotionEventActions.Move: { SetContext(view, Event); // Only accept the Event if our relative pressure is within // a certain limit - this can help filter shaky data as a // finger is lifted. if (MCurrPressure / MPrevPressure > PressureThreshold) { bool updatePrevious = MListener.OnScale(view, this); if (updatePrevious) { MPrevEvent.Recycle(); MPrevEvent = MotionEvent.Obtain(Event); } } } break; } } return(handled); } catch (Exception e) { Console.WriteLine(e); return(false); } }
public void SetContext(View view, MotionEvent curr) { try { if (MCurrEvent != null) { MCurrEvent.Recycle(); } MCurrEvent = MotionEvent.Obtain(curr); MCurrLen = -1; MPrevLen = -1; MScaleFactor = -1; MCurrSpanVector.Set(0.0f, 0.0f); MotionEvent prev = MPrevEvent; int prevIndex0 = prev.FindPointerIndex(MActiveId0); int prevIndex1 = prev.FindPointerIndex(MActiveId1); int currIndex0 = curr.FindPointerIndex(MActiveId0); int currIndex1 = curr.FindPointerIndex(MActiveId1); if (prevIndex0 < 0 || prevIndex1 < 0 || currIndex0 < 0 || currIndex1 < 0) { MInvalidGesture = true; Log.Error(Tag, "Invalid MotionEvent stream detected.", new Throwable()); if (MGestureInProgress) { MListener.OnScaleEnd(view, this); } return; } float px0 = prev.GetX(prevIndex0); float py0 = prev.GetY(prevIndex0); float px1 = prev.GetX(prevIndex1); float py1 = prev.GetY(prevIndex1); float cx0 = curr.GetX(currIndex0); float cy0 = curr.GetY(currIndex0); float cx1 = curr.GetX(currIndex1); float cy1 = curr.GetY(currIndex1); float pvx = px1 - px0; float pvy = py1 - py0; float cvx = cx1 - cx0; float cvy = cy1 - cy0; MCurrSpanVector.Set(cvx, cvy); MPrevFingerDiffX = pvx; MPrevFingerDiffY = pvy; MCurrFingerDiffX = cvx; MCurrFingerDiffY = cvy; MFocusX = cx0 + cvx * 0.5f; MFocusY = cy0 + cvy * 0.5f; MTimeDelta = curr.EventTime - prev.EventTime; MCurrPressure = curr.GetPressure(currIndex0) + curr.GetPressure(currIndex1); MPrevPressure = prev.GetPressure(prevIndex0) + prev.GetPressure(prevIndex1); } catch (Exception e) { Console.WriteLine(e); } }