public override bool DispatchTouchEvent(MotionEvent e) { bool ret = false; // vérifi que le InfoWindows est affiché if (_marker != null && _marker.IsInfoWindowShown && _map != null && _infoWindow != null) { // obtient la position du marker à l'écran Point point = _map.Projection.ToScreenLocation(_marker.Position); // ajustement du clique pour un pin Seekios MotionEvent seekiosRefresh = MotionEvent.ObtainNoHistory(e); seekiosRefresh.OffsetLocation( -point.X + (_infoWindow.Width / 2), -point.Y + _infoWindow.Height + _heightSeekios); // 130 = la hauteur du pin seekios // ajustement du clique pour un pin Marker MotionEvent copyEvMarker = MotionEvent.ObtainNoHistory(e); copyEvMarker.OffsetLocation( -point.X + (_infoWindow.Width / 2), -point.Y + _infoWindow.Height + _heightMarker); // 35 = la hauteur du pin marker // dispatch le MotionEvent ajusté vers le InfoWindow ret = _infoWindow.DispatchTouchEvent(seekiosRefresh); ret = _infoWindow.DispatchTouchEvent(copyEvMarker); } return(ret || base.DispatchTouchEvent(e)); }
private MotionEvent ObtainMotionEvent(MotionEvent source, MotionEventActions action) { MotionEvent ev = MotionEvent.ObtainNoHistory(source); ev.Action = action; return(ev); }
private void SendFakeEvent(MotionEvent e, MotionEventActions forcedAction) { var fake_event = MotionEvent.ObtainNoHistory(e); fake_event.Action = forcedAction; ContentView.ForceHandleTouchEvent(fake_event); fake_event.Recycle(); }
/** * 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, params MotionEvent[] pendingEvents) { if (ev == null) { return; } for (int i = ChildCount - 1; 0 <= i; i--) { View childView = GetChildAt(i); if (childView != null) { Rect childRect = new Rect(); childView.GetHitRect(childRect); MotionEvent event2 = MotionEvent.ObtainNoHistory(ev); if (!childRect.Contains((int)event2.GetX(), (int)event2.GetY())) { continue; } float offsetX = -childView.Left; float offsetY = -childView.Top; bool consumed = false; if (pendingEvents != null) { foreach (MotionEvent pe in pendingEvents) { if (pe != null) { MotionEvent peAdjusted = MotionEvent.ObtainNoHistory(pe); peAdjusted.OffsetLocation(offsetX, offsetY); consumed |= childView.DispatchTouchEvent(peAdjusted); } } } event2.OffsetLocation(offsetX, offsetY); consumed |= childView.DispatchTouchEvent(event2); if (consumed) { break; } } } }
public override bool OnInterceptTouchEvent(MotionEvent ev) { if (_mTouchInterceptionListener == null) { return(false); } // In here, we must initialize touch state variables // and ask if we should intercept this event. // Whether we should intercept or not is kept for the later event handling. switch (ev.ActionMasked) { case MotionEventActions.Down: _mInitialPoint = new PointF(ev.GetX(), ev.GetY()); _mPendingDownMotionEvent = MotionEvent.ObtainNoHistory(ev); _mDownMotionEventPended = true; _mIntercepting = _mTouchInterceptionListener.ShouldInterceptTouchEvent(ev, false, 0, 0); _mBeganFromDownMotionEvent = _mIntercepting; _mChildrenEventsCanceled = false; return(_mIntercepting); case MotionEventActions.Move: // ACTION_MOVE will be passed suddenly, so initialize to avoid exception. if (_mInitialPoint == null) { _mInitialPoint = new PointF(ev.GetX(), ev.GetY()); } // diffX and diffY are the origin of the motion, and should be difference // from the position of the ACTION_DOWN event occurred. float diffX = ev.GetX() - _mInitialPoint.X; float diffY = ev.GetY() - _mInitialPoint.Y; _mIntercepting = _mTouchInterceptionListener.ShouldInterceptTouchEvent(ev, true, diffX, diffY); return(_mIntercepting); } return(false); }
public override bool OnTouchEvent(MotionEvent ev) { if (_mCallbacks != null) { switch (ev.ActionMasked) { case MotionEventActions.Up: case MotionEventActions.Cancel: _mIntercepted = false; _mDragging = false; _mCallbacks.OnUpOrCancelMotionEvent(_mScrollState); break; case MotionEventActions.Move: if (_mPrevMoveEvent == null) { _mPrevMoveEvent = ev; } float diffY = ev.GetY() - _mPrevMoveEvent.GetY(); _mPrevMoveEvent = MotionEvent.ObtainNoHistory(ev); if (GetCurrentScrollY() - diffY <= 0) { // Can't scroll anymore. if (_mIntercepted) { // Already dispatched ACTION_DOWN event to parents, so stop here. return(false); } // Apps can set the interception target other than the direct parent. ViewGroup parent; if (_mTouchInterceptionViewGroup == null) { parent = (ViewGroup)Parent; } else { parent = _mTouchInterceptionViewGroup; } // Get offset to parents. If the parent is not the direct parent, // we should aggregate offsets from all of the parents. float offsetX = 0; float offsetY = 0; for (View v = this; v != null && v != parent; v = (View)v.Parent) { offsetX += v.Left - v.ScrollX; offsetY += v.Top - v.ScrollY; } MotionEvent eventHistoryLess = MotionEvent.ObtainNoHistory(ev); eventHistoryLess.OffsetLocation(offsetX, offsetY); if (parent.OnInterceptTouchEvent(eventHistoryLess)) { _mIntercepted = true; // If the parent wants to intercept ACTION_MOVE events, // we pass ACTION_DOWN event to the parent // as if these touch events just have began now. eventHistoryLess.Action = MotionEventActions.Down; // Return this onTouchEvent() first and set ACTION_DOWN event for parent // to the queue, to keep events sequence. Post(() => parent.DispatchTouchEvent(eventHistoryLess)); return(false); } // Even when this can't be scrolled anymore, // simply returning false here may cause subView's click, // so delegate it to super. return(base.OnTouchEvent(ev)); } break; } } return(base.OnTouchEvent(ev)); }
public override bool OnTouchEvent(MotionEvent ev) { if (_mTouchInterceptionListener != null) { switch (ev.ActionMasked) { case MotionEventActions.Down: if (_mIntercepting) { _mTouchInterceptionListener.OnDownMotionEvent(ev); DuplicateTouchEventForChildren(ev); return(true); } break; case MotionEventActions.Move: // ACTION_MOVE will be passed suddenly, so initialize to avoid exception. if (_mInitialPoint == null) { _mInitialPoint = new PointF(ev.GetX(), ev.GetY()); } // diffX and diffY are the origin of the motion, and should be difference // from the position of the ACTION_DOWN event occurred. float diffX = ev.GetX() - _mInitialPoint.X; float diffY = ev.GetY() - _mInitialPoint.Y; _mIntercepting = _mTouchInterceptionListener.ShouldInterceptTouchEvent(ev, true, diffX, diffY); if (_mIntercepting) { // If this layout didn't receive ACTION_DOWN motion event, // we should generate ACTION_DOWN event with current position. if (!_mBeganFromDownMotionEvent) { _mBeganFromDownMotionEvent = true; MotionEvent event2 = MotionEvent.ObtainNoHistory(_mPendingDownMotionEvent); event2.SetLocation(ev.GetX(), ev.GetY()); _mTouchInterceptionListener.OnDownMotionEvent(event2); _mInitialPoint = new PointF(ev.GetX(), ev.GetY()); diffX = diffY = 0; } // Children's touches should be canceled if (!_mChildrenEventsCanceled) { _mChildrenEventsCanceled = true; DuplicateTouchEventForChildren(ObtainMotionEvent(ev, MotionEventActions.Cancel)); } _mTouchInterceptionListener.OnMoveMotionEvent(ev, diffX, diffY); // If next mIntercepting become false, // then we should generate fake ACTION_DOWN event. // Therefore we set pending flag to true as if this is a down motion event. _mDownMotionEventPended = true; // Whether or not this event is consumed by the listener, // assume it consumed because we declared to intercept the event. return(true); } if (_mDownMotionEventPended) { _mDownMotionEventPended = false; MotionEvent event2 = MotionEvent.ObtainNoHistory(_mPendingDownMotionEvent); event2.SetLocation(ev.GetX(), ev.GetY()); DuplicateTouchEventForChildren(ev, event2); } else { DuplicateTouchEventForChildren(ev); } // If next mIntercepting become true, // then we should generate fake ACTION_DOWN event. // Therefore we set beganFromDownMotionEvent flag to false // as if we haven't received a down motion event. _mBeganFromDownMotionEvent = false; // Reserve children's click cancellation here if they've already canceled _mChildrenEventsCanceled = false; break; case MotionEventActions.Up: case MotionEventActions.Cancel: _mBeganFromDownMotionEvent = false; if (_mIntercepting) { _mTouchInterceptionListener.OnUpOrCancelMotionEvent(ev); } // Children's touches should be canceled regardless of // whether or not this layout intercepted the consecutive motion events. if (!_mChildrenEventsCanceled) { _mChildrenEventsCanceled = true; if (_mDownMotionEventPended) { _mDownMotionEventPended = false; MotionEvent event2 = MotionEvent.ObtainNoHistory(_mPendingDownMotionEvent); event2.SetLocation(ev.GetX(), ev.GetY()); DuplicateTouchEventForChildren(ev, event2); } else { DuplicateTouchEventForChildren(ev); } } return(true); } } return(base.OnTouchEvent(ev)); }