void CheckForBoundaryHop(int id, Point pointerLocation) { TouchEffect touchEffectHit = null; foreach (global::Android.Views.View view in viewDictionary.Keys) { // Get the view rectangle try { view.GetLocationOnScreen(twoIntArray); } catch // System.ObjectDisposedException: Cannot access a disposed object. { continue; } Rectangle viewRect = new Rectangle(twoIntArray[0], twoIntArray[1], view.Width, view.Height); if (viewRect.Contains(pointerLocation)) { touchEffectHit = viewDictionary[view]; } } if (touchEffectHit != idToEffectDictionary[id]) { if (idToEffectDictionary[id] != null) { FireEvent(idToEffectDictionary[id], id, TouchActionType.Exited, pointerLocation, true); } if (touchEffectHit != null) { FireEvent(touchEffectHit, id, TouchActionType.Entered, pointerLocation, true); } idToEffectDictionary[id] = touchEffectHit; } }
void OnTouch(object sender, global::Android.Views.View.TouchEventArgs args) { // Two object common to all the events global::Android.Views.View senderView = sender as global::Android.Views.View; MotionEvent motionEvent = args.Event; // Get the pointer index int pointerIndex = motionEvent.ActionIndex; // Get the id that identifies a finger over the course of its progress int id = motionEvent.GetPointerId(pointerIndex); senderView.GetLocationOnScreen(twoIntArray); Point screenPointerCoords = new Point(twoIntArray[0] + motionEvent.GetX(pointerIndex), twoIntArray[1] + motionEvent.GetY(pointerIndex)); // Use ActionMasked here rather than Action to reduce the number of possibilities switch (args.Event.ActionMasked) { case MotionEventActions.Down: case MotionEventActions.PointerDown: FireEvent(this, id, TouchActionType.Pressed, screenPointerCoords, true); if (!idToEffectDictionary.ContainsKey(id)) { idToEffectDictionary.Add(id, this); } capture = pclTouchEffect.Capture; break; case MotionEventActions.Move: // Multiple Move events are bundled, so handle them in a loop for (pointerIndex = 0; pointerIndex < motionEvent.PointerCount; pointerIndex++) { id = motionEvent.GetPointerId(pointerIndex); if (capture) { senderView.GetLocationOnScreen(twoIntArray); screenPointerCoords = new Point(twoIntArray[0] + motionEvent.GetX(pointerIndex), twoIntArray[1] + motionEvent.GetY(pointerIndex)); FireEvent(this, id, TouchActionType.Moved, screenPointerCoords, true); } else { CheckForBoundaryHop(id, screenPointerCoords); if (idToEffectDictionary[id] != null) { FireEvent(idToEffectDictionary[id], id, TouchActionType.Moved, screenPointerCoords, true); } } } break; case MotionEventActions.Up: case MotionEventActions.Pointer1Up: if (capture) { FireEvent(this, id, TouchActionType.Released, screenPointerCoords, false); } else { CheckForBoundaryHop(id, screenPointerCoords); if (idToEffectDictionary[id] != null) { FireEvent(idToEffectDictionary[id], id, TouchActionType.Released, screenPointerCoords, false); } } idToEffectDictionary.Remove(id); break; case MotionEventActions.Cancel: if (capture) { FireEvent(this, id, TouchActionType.Cancelled, screenPointerCoords, false); } else { if (idToEffectDictionary[id] != null) { FireEvent(idToEffectDictionary[id], id, TouchActionType.Cancelled, screenPointerCoords, false); } } idToEffectDictionary.Remove(id); break; } }