public void OnTouchEvent(global::Android.Views.MotionEvent e, CanvasContent content) { if (content == null) { throw new ArgumentNullException("content"); } if (e == null) { throw new ArgumentNullException("e"); } var began = new List <CanvasTouch> (); var moved = new List <CanvasTouch> (); var ended = new List <CanvasTouch> (); var cancelled = new List <CanvasTouch> (); var pointerCount = e.PointerCount; var actionMasked = e.Action & global::Android.Views.MotionEventActions.Mask; var actionIndex = (int)(e.Action & global::Android.Views.MotionEventActions.PointerIdMask) >> (int)global::Android.Views.MotionEventActions.PointerIdShift; var actionId = e.GetPointerId(actionIndex); //Log.WriteLine("a = {0}, index = {1}, id = {2}, c = {3}", actionMasked, actionIndex, actionId, pointerCount); switch (actionMasked) { case global::Android.Views.MotionEventActions.Move: for (var index = 0; index < pointerCount; index++) { var id = e.GetPointerId(index); if (id < MaxTouchId) { var t = _activeTouches[id]; if (t != null) { var curSuperLoc = t.SuperCanvasLocation; var newSuperLoc = new System.Drawing.PointF(e.GetX(index), e.GetY(index)); var dx = curSuperLoc.X - newSuperLoc.X; var dy = curSuperLoc.Y - newSuperLoc.Y; if (t.IsMoving || (Math.Abs(dx) > _initialMoveResolution || Math.Abs(dy) > _initialMoveResolution) || NumActiveTouches > 1) { t.SuperCanvasPreviousLocation = t.SuperCanvasLocation; t.CanvasPreviousLocation = t.CanvasLocation; t.PreviousTime = t.Time; t.IsMoving = true; t.SuperCanvasLocation = newSuperLoc; t.CanvasLocation = LocationFromView(t.SuperCanvasLocation); t.Time = DateTime.UtcNow; moved.Add(t); _longClickToken = -1; } } } } break; case global::Android.Views.MotionEventActions.Down: case global::Android.Views.MotionEventActions.PointerDown: if (actionId < MaxTouchId) { var t = new AndroidTouch { Handle = new IntPtr(actionId + 1), // +1 because IntPtr=0 is special SuperCanvasLocation = new System.Drawing.PointF(e.GetX(actionIndex), e.GetY(actionIndex)), Time = DateTime.UtcNow, TapCount = 1, }; t.CanvasLocation = LocationFromView(t.SuperCanvasLocation); t.CanvasPreviousLocation = t.CanvasLocation; t.SuperCanvasPreviousLocation = t.SuperCanvasLocation; t.PreviousTime = t.Time; began.Add(t); _activeTouches[actionId] = t; // // Detect double tap // if ((t.Time - _lastBeganTime).TotalMilliseconds <= _doubleTapTimeoutMillis && Math.Abs(_lastBeganLocation.X - t.SuperCanvasLocation.X) <= _doubleTapResolution && Math.Abs(_lastBeganLocation.Y - t.SuperCanvasLocation.Y) <= _doubleTapResolution) { t.TapCount = 2; } else { // // Detect long press // if (NumActiveTouches == 1) { var tok = _longClickTokenGenerator.Next(); _handler.PostDelayed(() => { HandleLongClick(tok, content); }, _longClickTimeoutMillis); _longClickToken = tok; } else { _longClickToken = -1; } } _lastBeganTime = t.Time; _lastBeganLocation = t.SuperCanvasLocation; } break; case global::Android.Views.MotionEventActions.Up: case global::Android.Views.MotionEventActions.PointerUp: if (actionId < MaxTouchId) { var t = _activeTouches[actionId]; if (t != null) { t.Time = DateTime.UtcNow; _activeTouches[actionId] = null; ended.Add(t); } _longClickToken = -1; } break; } if (began.Count > 0) { content.TouchesBegan(began.ToArray(), CanvasKeys.None); } if (moved.Count > 0) { content.TouchesMoved(moved.ToArray()); } if (ended.Count > 0) { content.TouchesEnded(ended.ToArray()); } if (cancelled.Count > 0) { content.TouchesCancelled(cancelled.ToArray()); } }
public override void Draw(global::Android.Graphics.Canvas canvas) { // // Start drawing // var del = Content; if (del == null) { return; } var startT = DateTime.Now; var _graphics = new AndroidGraphics(canvas); _graphics.SaveState(); _graphics.Scale(Zoom, Zoom); // // Draw // del.Frame = new RectangleF(0, 0, Width / Zoom, Height / Zoom); try { del.Draw(_graphics); } catch (Exception) { } _graphics.RestoreState(); var endT = DateTime.Now; _drawTime += (endT - startT).TotalSeconds; _drawCount++; // // Throttle // if (_running && _drawCount > 2 && (DateTime.Now - _lastThrottleTime) >= ThrottleInterval) { _lastThrottleTime = DateTime.Now; var maxfps = 1.0 / (_drawTime / _drawCount); _drawTime = 0; _drawCount = 0; var fps = ClampUpdateFreq((int)(maxfps * CpuUtilization)); if (Math.Abs(fps - _fps) > 1) { _fps = fps; Start(); } } // // Notify // var df = DrewFrame; if (df != null) { df(this, EventArgs.Empty); } if (_running) { _handler.PostDelayed(HandleDrawTimerElapsed, 1000 / _fps); } }