Merge pull request #309 from mono/touch-events

Adding touch events
This commit is contained in:
Matthew Leibowitz 2017-06-09 18:18:57 +02:00 коммит произвёл GitHub
Родитель 3f00bc3eb1 5380c160dc
Коммит 13fd5bc765
16 изменённых файлов: 714 добавлений и 2 удалений

Просмотреть файл

@ -0,0 +1,95 @@
using System;
using Android.Views;
namespace SkiaSharp.Views.Forms
{
internal class SKTouchHandler
{
private Action<SKTouchEventArgs> onTouchAction;
private Func<float, float> scalePixels;
public SKTouchHandler(Action<SKTouchEventArgs> onTouchAction, Func<float, float> scalePixels)
{
this.onTouchAction = onTouchAction;
this.scalePixels = scalePixels;
}
public void SetEnabled(View view, bool enableTouchEvents)
{
if (view != null)
{
view.Touch -= OnTouch;
if (enableTouchEvents)
{
view.Touch += OnTouch;
}
}
}
public void Detach(View view)
{
// clean the view
SetEnabled(view, false);
// remove references
onTouchAction = null;
scalePixels = null;
}
private void OnTouch(object sender, View.TouchEventArgs e)
{
if (onTouchAction == null || scalePixels == null)
return;
var evt = e.Event;
var pointer = evt.ActionIndex;
var id = evt.GetPointerId(pointer);
var coords = new SKPoint(scalePixels(evt.GetX(pointer)), scalePixels(evt.GetY(pointer)));
switch (evt.ActionMasked)
{
case MotionEventActions.Down:
case MotionEventActions.PointerDown:
{
var args = new SKTouchEventArgs(id, SKTouchAction.Pressed, coords, true);
onTouchAction(args);
e.Handled = args.Handled;
break;
}
case MotionEventActions.Move:
{
var count = evt.PointerCount;
for (pointer = 0; pointer < count; pointer++)
{
id = evt.GetPointerId(pointer);
coords = new SKPoint(scalePixels(evt.GetX(pointer)), scalePixels(evt.GetY(pointer)));
var args = new SKTouchEventArgs(id, SKTouchAction.Moved, coords, true);
onTouchAction(args);
e.Handled = e.Handled || args.Handled;
}
break;
}
case MotionEventActions.Up:
case MotionEventActions.PointerUp:
{
var args = new SKTouchEventArgs(id, SKTouchAction.Released, coords, false);
onTouchAction(args);
e.Handled = args.Handled;
break;
}
case MotionEventActions.Cancel:
{
var args = new SKTouchEventArgs(id, SKTouchAction.Cancelled, coords, false);
onTouchAction(args);
e.Handled = args.Handled;
break;
}
}
}
}
}

Просмотреть файл

@ -85,6 +85,7 @@
<Compile Include="SKCanvasViewRenderer.cs" />
<Compile Include="SKGLViewRenderer.cs" />
<Compile Include="SKImageSourceHandler.cs" />
<Compile Include="SKTouchHandler.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

Просмотреть файл

@ -0,0 +1,125 @@
using System;
using System.Linq;
using Foundation;
using AppKit;
namespace SkiaSharp.Views.Forms
{
internal class SKTouchHandler : NSGestureRecognizer
{
private Action<SKTouchEventArgs> onTouchAction;
private Func<nfloat, nfloat> scalePixels;
public SKTouchHandler(Action<SKTouchEventArgs> onTouchAction, Func<nfloat, nfloat> scalePixels)
{
this.onTouchAction = onTouchAction;
this.scalePixels = scalePixels;
}
public void SetEnabled(NSView view, bool enableTouchEvents)
{
if (view != null)
{
if (enableTouchEvents && !view.GestureRecognizers.Contains(this))
{
view.AddGestureRecognizer(this);
}
else if (!enableTouchEvents && view.GestureRecognizers.Contains(this))
{
view.RemoveGestureRecognizer(this);
}
}
}
public void Detach(NSView view)
{
// clean the view
SetEnabled(view, false);
// remove references
onTouchAction = null;
scalePixels = null;
}
public override void MouseDown(NSEvent mouseEvent)
{
base.MouseDown(mouseEvent);
FireEvent(SKTouchAction.Pressed, SKMouseButton.Left, SKTouchDeviceType.Mouse, mouseEvent, true);
}
public override void MouseUp(NSEvent mouseEvent)
{
base.MouseUp(mouseEvent);
FireEvent(SKTouchAction.Released, SKMouseButton.Left, SKTouchDeviceType.Mouse, mouseEvent, false);
}
public override void MouseDragged(NSEvent mouseEvent)
{
base.MouseDragged(mouseEvent);
FireEvent(SKTouchAction.Moved, SKMouseButton.Left, SKTouchDeviceType.Mouse, mouseEvent, true);
}
public override void OtherMouseDown(NSEvent mouseEvent)
{
base.OtherMouseDown(mouseEvent);
FireEvent(SKTouchAction.Pressed, SKMouseButton.Middle, SKTouchDeviceType.Mouse, mouseEvent, true);
}
public override void OtherMouseUp(NSEvent mouseEvent)
{
base.OtherMouseUp(mouseEvent);
FireEvent(SKTouchAction.Released, SKMouseButton.Middle, SKTouchDeviceType.Mouse, mouseEvent, false);
}
public override void OtherMouseDragged(NSEvent mouseEvent)
{
base.OtherMouseDragged(mouseEvent);
FireEvent(SKTouchAction.Moved, SKMouseButton.Middle, SKTouchDeviceType.Mouse, mouseEvent, true);
}
public override void RightMouseDown(NSEvent mouseEvent)
{
base.RightMouseDown(mouseEvent);
FireEvent(SKTouchAction.Pressed, SKMouseButton.Right, SKTouchDeviceType.Mouse, mouseEvent, true);
}
public override void RightMouseUp(NSEvent mouseEvent)
{
base.RightMouseUp(mouseEvent);
FireEvent(SKTouchAction.Released, SKMouseButton.Right, SKTouchDeviceType.Mouse, mouseEvent, false);
}
public override void RightMouseDragged(NSEvent mouseEvent)
{
base.RightMouseDragged(mouseEvent);
FireEvent(SKTouchAction.Moved, SKMouseButton.Right, SKTouchDeviceType.Mouse, mouseEvent, true);
}
private bool FireEvent(SKTouchAction actionType, SKMouseButton mouse, SKTouchDeviceType device, NSEvent mouseEvent, bool inContact)
{
if (onTouchAction == null || scalePixels == null)
return false;
var id = mouseEvent.ButtonNumber;
var cgPoint = LocationInView(View);
// flip the Y coordinate for macOS
cgPoint.Y = View.Bounds.Height - cgPoint.Y;
var point = new SKPoint((float)scalePixels(cgPoint.X), (float)scalePixels(cgPoint.Y));
var args = new SKTouchEventArgs(id, actionType, mouse, device, point, inContact);
onTouchAction(args);
return args.Handled;
}
}
}

Просмотреть файл

@ -61,6 +61,7 @@
<Compile Include="SKCanvasViewRenderer.cs" />
<Compile Include="SKGLViewRenderer.cs" />
<Compile Include="SKImageSourceHandler.cs" />
<Compile Include="SKTouchHandler.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\SkiaSharp.Views\SkiaSharp.Views.Mac\SkiaSharp.Views.Mac.csproj">

Просмотреть файл

@ -12,6 +12,7 @@ using Xamarin.Forms.Platform.iOS;
using SKNativeView = SkiaSharp.Views.iOS.SKCanvasView;
using SKNativePaintSurfaceEventArgs = SkiaSharp.Views.iOS.SKPaintSurfaceEventArgs;
#elif WINDOWS_UWP
using Windows.Graphics.Display;
using Xamarin.Forms.Platform.UWP;
using SKNativeView = SkiaSharp.Views.UWP.SKXamlCanvas;
using SKNativePaintSurfaceEventArgs = SkiaSharp.Views.UWP.SKPaintSurfaceEventArgs;
@ -27,6 +28,36 @@ namespace SkiaSharp.Views.Forms
where TFormsView : SKFormsView
where TNativeView : SKNativeView
{
private readonly SKTouchHandler touchHandler;
public SKCanvasViewRendererBase()
{
#if __ANDROID__
touchHandler = new SKTouchHandler(
args => ((ISKCanvasViewController)Element).OnTouch(args),
coord => Element.IgnorePixelScaling ? (float)Context.FromPixels(coord) : coord);
#elif __IOS__
touchHandler = new SKTouchHandler(
args => ((ISKCanvasViewController)Element).OnTouch(args),
coord => Element.IgnorePixelScaling ? coord : coord * Control.ContentScaleFactor);
#elif __MACOS__
touchHandler = new SKTouchHandler(
args => ((ISKCanvasViewController)Element).OnTouch(args),
coord => Element.IgnorePixelScaling ? coord : coord * Control.Window.BackingScaleFactor);
#elif WINDOWS_UWP
touchHandler = new SKTouchHandler(
args => ((ISKCanvasViewController)Element).OnTouch(args),
coord => Element.IgnorePixelScaling ? coord : (float)(coord * Control.Dpi));
#endif
}
#if __IOS__
protected void SetDisablesUserInteraction(bool disablesUserInteraction)
{
touchHandler.DisablesUserInteraction = disablesUserInteraction;
}
#endif
protected override void OnElementChanged(ElementChangedEventArgs<TFormsView> e)
{
if (e.OldElement != null)
@ -51,6 +82,7 @@ namespace SkiaSharp.Views.Forms
}
// set the initial values
touchHandler.SetEnabled(Control, e.NewElement.EnableTouchEvents);
Control.IgnorePixelScaling = e.NewElement.IgnorePixelScaling;
// subscribe to events from the user
@ -84,6 +116,10 @@ namespace SkiaSharp.Views.Forms
{
Control.IgnorePixelScaling = Element.IgnorePixelScaling;
}
else if (e.PropertyName == SKFormsView.EnableTouchEventsProperty.PropertyName)
{
touchHandler.SetEnabled(Control, Element.EnableTouchEvents);
}
}
protected override void Dispose(bool disposing)
@ -102,6 +138,9 @@ namespace SkiaSharp.Views.Forms
control.PaintSurface -= OnPaintSurface;
}
// detach, regardless of state
touchHandler.Detach(control);
base.Dispose(disposing);
}

Просмотреть файл

@ -28,6 +28,36 @@ namespace SkiaSharp.Views.Forms
where TFormsView : SKFormsView
where TNativeView : SKNativeView
{
private readonly SKTouchHandler touchHandler;
public SKGLViewRendererBase()
{
#if __ANDROID__
touchHandler = new SKTouchHandler(
args => ((ISKGLViewController)Element).OnTouch(args),
coord => coord);
#elif __IOS__
touchHandler = new SKTouchHandler(
args => ((ISKGLViewController)Element).OnTouch(args),
coord => coord * Control.ContentScaleFactor);
#elif __MACOS__
touchHandler = new SKTouchHandler(
args => ((ISKGLViewController)Element).OnTouch(args),
coord => coord * Control.Window.BackingScaleFactor);
#elif WINDOWS_UWP
touchHandler = new SKTouchHandler(
args => ((ISKGLViewController)Element).OnTouch(args),
coord => (float)(coord * Control.ContentsScale));
#endif
}
#if __IOS__
protected void SetDisablesUserInteraction(bool disablesUserInteraction)
{
touchHandler.DisablesUserInteraction = disablesUserInteraction;
}
#endif
protected override void OnElementChanged(ElementChangedEventArgs<TFormsView> e)
{
if (e.OldElement != null)
@ -55,6 +85,8 @@ namespace SkiaSharp.Views.Forms
SetNativeControl(view);
}
touchHandler.SetEnabled(Control, e.NewElement.EnableTouchEvents);
// subscribe to events from the user
newController.SurfaceInvalidated += OnSurfaceInvalidated;
newController.GetCanvasSize += OnGetCanvasSize;
@ -87,6 +119,10 @@ namespace SkiaSharp.Views.Forms
{
SetupRenderLoop(false);
}
else if (e.PropertyName == SKFormsView.EnableTouchEventsProperty.PropertyName)
{
touchHandler.SetEnabled(Control, Element.EnableTouchEvents);
}
}
protected override void Dispose(bool disposing)
@ -108,6 +144,9 @@ namespace SkiaSharp.Views.Forms
#endif
}
// detach, regardless of state
touchHandler.Detach(control);
base.Dispose(disposing);
}

Просмотреть файл

@ -9,9 +9,15 @@ namespace SkiaSharp.Views.Forms
public static readonly BindableProperty IgnorePixelScalingProperty =
BindableProperty.Create(nameof(IgnorePixelScaling), typeof(bool), typeof(SKCanvasView), false);
public static readonly BindableProperty EnableTouchEventsProperty =
BindableProperty.Create(nameof(EnableTouchEvents), typeof(bool), typeof(SKCanvasView), false);
// the user can subscribe to repaint
public event EventHandler<SKPaintSurfaceEventArgs> PaintSurface;
// the user can subscribe to touch events
public event EventHandler<SKTouchEventArgs> Touch;
// the native listens to this event
private event EventHandler SurfaceInvalidated;
private event EventHandler<GetCanvasSizeEventArgs> GetCanvasSize;
@ -34,6 +40,12 @@ namespace SkiaSharp.Views.Forms
set { SetValue(IgnorePixelScalingProperty, value); }
}
public bool EnableTouchEvents
{
get { return (bool)GetValue(EnableTouchEventsProperty); }
set { SetValue(EnableTouchEventsProperty, value); }
}
// the user asks to repaint
public void InvalidateSurface()
{
@ -47,6 +59,12 @@ namespace SkiaSharp.Views.Forms
PaintSurface?.Invoke(this, e);
}
// the native view responds to a touch
protected virtual void OnTouch(SKTouchEventArgs e)
{
Touch?.Invoke(this, e);
}
// ISKViewController implementation
event EventHandler ISKCanvasViewController.SurfaceInvalidated
@ -66,6 +84,11 @@ namespace SkiaSharp.Views.Forms
OnPaintSurface(e);
}
void ISKCanvasViewController.OnTouch(SKTouchEventArgs e)
{
OnTouch(e);
}
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
return new SizeRequest(new Size(40.0, 40.0));
@ -80,5 +103,8 @@ namespace SkiaSharp.Views.Forms
// the native view tells the user to repaint
void OnPaintSurface(SKPaintSurfaceEventArgs e);
// the native view responds to a touch
void OnTouch(SKTouchEventArgs e);
}
}

Просмотреть файл

@ -9,15 +9,27 @@ namespace SkiaSharp.Views.Forms
public static readonly BindableProperty HasRenderLoopProperty =
BindableProperty.Create(nameof(HasRenderLoop), typeof(bool), typeof(SKGLView), false);
public static readonly BindableProperty EnableTouchEventsProperty =
BindableProperty.Create(nameof(EnableTouchEvents), typeof(bool), typeof(SKGLView), false);
public bool HasRenderLoop
{
get { return (bool)GetValue(HasRenderLoopProperty); }
set { SetValue(HasRenderLoopProperty, value); }
}
public bool EnableTouchEvents
{
get { return (bool)GetValue(EnableTouchEventsProperty); }
set { SetValue(EnableTouchEventsProperty, value); }
}
// the user can subscribe to repaint
public event EventHandler<SKPaintGLSurfaceEventArgs> PaintSurface;
// the user can subscribe to touch events
public event EventHandler<SKTouchEventArgs> Touch;
// the native listens to this event
private event EventHandler SurfaceInvalidated;
private event EventHandler<GetCanvasSizeEventArgs> GetCanvasSize;
@ -47,6 +59,12 @@ namespace SkiaSharp.Views.Forms
PaintSurface?.Invoke(this, e);
}
// the native view responds to a touch
protected virtual void OnTouch(SKTouchEventArgs e)
{
Touch?.Invoke(this, e);
}
// ISKViewController implementation
event EventHandler ISKGLViewController.SurfaceInvalidated
@ -66,6 +84,11 @@ namespace SkiaSharp.Views.Forms
OnPaintSurface(e);
}
void ISKGLViewController.OnTouch(SKTouchEventArgs e)
{
OnTouch(e);
}
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
return new SizeRequest(new Size(40.0, 40.0));
@ -80,5 +103,8 @@ namespace SkiaSharp.Views.Forms
// the native view tells the user to repaint
void OnPaintSurface(SKPaintGLSurfaceEventArgs e);
// the native view responds to a touch
void OnTouch(SKTouchEventArgs e);
}
}

Просмотреть файл

@ -0,0 +1,70 @@
using System;
using System.Linq;
namespace SkiaSharp.Views.Forms
{
public class SKTouchEventArgs : EventArgs
{
public SKTouchEventArgs(long id, SKTouchAction type, SKPoint location, bool inContact)
: this(id, type, SKMouseButton.Left, SKTouchDeviceType.Touch, location, inContact)
{
}
public SKTouchEventArgs(long id, SKTouchAction type, SKMouseButton mouseButton, SKTouchDeviceType deviceType, SKPoint location, bool inContact)
{
Id = id;
ActionType = type;
DeviceType = deviceType;
MouseButton = mouseButton;
Location = location;
InContact = inContact;
Handled = true;
}
// this may be removed, but for now keep it
internal bool Handled { get; set; }
public long Id { get; private set; }
public SKTouchAction ActionType { get; private set; }
public SKTouchDeviceType DeviceType { get; private set; }
public SKMouseButton MouseButton { get; private set; }
public SKPoint Location { get; private set; }
public bool InContact { get; private set; }
public override string ToString()
{
return $"{{ActionType={ActionType}, DeviceType={DeviceType}, Id={Id}, InContact={InContact}, Location={Location}, MouseButton={MouseButton}}}";
}
}
public enum SKTouchAction
{
Entered,
Pressed,
Moved,
Released,
Cancelled,
Exited,
}
public enum SKTouchDeviceType
{
Touch,
Mouse,
Pen
}
public enum SKMouseButton
{
Unknown,
Left,
Middle,
Right
}
}

Просмотреть файл

@ -17,5 +17,6 @@
<Compile Include="$(MSBuildThisFileDirectory)SKCanvasView.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RendererTypes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SKImageSource.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SKTouchEventArgs.cs" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,172 @@
using System;
using Windows.Devices.Input;
using Windows.UI.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Input;
namespace SkiaSharp.Views.Forms
{
internal class SKTouchHandler
{
private Action<SKTouchEventArgs> onTouchAction;
private Func<float, float> scalePixels;
public SKTouchHandler(Action<SKTouchEventArgs> onTouchAction, Func<float, float> scalePixels)
{
this.onTouchAction = onTouchAction;
this.scalePixels = scalePixels;
}
public void SetEnabled(FrameworkElement view, bool enableTouchEvents)
{
if (view != null)
{
view.PointerEntered -= OnPointerEntered;
view.PointerExited -= OnPointerExited;
view.PointerPressed -= OnPointerPressed;
view.PointerMoved -= OnPointerMoved;
view.PointerReleased -= OnPointerReleased;
view.PointerCanceled -= OnPointerCancelled;
if (enableTouchEvents)
{
view.PointerEntered += OnPointerEntered;
view.PointerExited += OnPointerExited;
view.PointerPressed += OnPointerPressed;
view.PointerMoved += OnPointerMoved;
view.PointerReleased += OnPointerReleased;
view.PointerCanceled += OnPointerCancelled;
}
}
}
public void Detach(FrameworkElement view)
{
// clean the view
SetEnabled(view, false);
// remove references
onTouchAction = null;
scalePixels = null;
}
private void OnPointerEntered(object sender, PointerRoutedEventArgs args)
{
CommonHandler(sender, SKTouchAction.Entered, args);
}
private void OnPointerExited(object sender, PointerRoutedEventArgs args)
{
CommonHandler(sender, SKTouchAction.Exited, args);
}
private void OnPointerPressed(object sender, PointerRoutedEventArgs args)
{
CommonHandler(sender, SKTouchAction.Pressed, args);
var view = sender as FrameworkElement;
view.CapturePointer(args.Pointer);
}
private void OnPointerMoved(object sender, PointerRoutedEventArgs args)
{
CommonHandler(sender, SKTouchAction.Moved, args);
}
private void OnPointerReleased(object sender, PointerRoutedEventArgs args)
{
CommonHandler(sender, SKTouchAction.Released, args);
}
private void OnPointerCancelled(object sender, PointerRoutedEventArgs args)
{
CommonHandler(sender, SKTouchAction.Cancelled, args);
}
private bool CommonHandler(object sender, SKTouchAction touchActionType, PointerRoutedEventArgs evt)
{
if (onTouchAction == null || scalePixels == null)
return false;
var view = sender as FrameworkElement;
var id = evt.Pointer.PointerId;
var pointerPoint = evt.GetCurrentPoint(view);
var windowsPoint = pointerPoint.Position;
var skPoint = new SKPoint(scalePixels((float)windowsPoint.X), scalePixels((float)windowsPoint.Y));
var mouse = GetMouseButton(pointerPoint);
var device = GetTouchDevice(evt);
var args = new SKTouchEventArgs(id, touchActionType, mouse, device, skPoint, evt.Pointer.IsInContact);
onTouchAction(args);
return args.Handled;
}
private static SKTouchDeviceType GetTouchDevice(PointerRoutedEventArgs evt)
{
var device = SKTouchDeviceType.Touch;
switch (evt.Pointer.PointerDeviceType)
{
case PointerDeviceType.Pen:
device = SKTouchDeviceType.Pen;
break;
case PointerDeviceType.Mouse:
device = SKTouchDeviceType.Mouse;
break;
case PointerDeviceType.Touch:
device = SKTouchDeviceType.Touch;
break;
}
return device;
}
private static SKMouseButton GetMouseButton(PointerPoint pointerPoint)
{
var properties = pointerPoint.Properties;
var mouse = SKMouseButton.Unknown;
// this is mainly for touch
if (properties.IsLeftButtonPressed)
{
mouse = SKMouseButton.Left;
}
else if (properties.IsMiddleButtonPressed)
{
mouse = SKMouseButton.Middle;
}
else if (properties.IsRightButtonPressed)
{
mouse = SKMouseButton.Right;
}
// this is mainly for mouse
switch (properties.PointerUpdateKind)
{
case PointerUpdateKind.LeftButtonPressed:
case PointerUpdateKind.LeftButtonReleased:
mouse = SKMouseButton.Left;
break;
case PointerUpdateKind.RightButtonPressed:
case PointerUpdateKind.RightButtonReleased:
mouse = SKMouseButton.Right;
break;
case PointerUpdateKind.MiddleButtonPressed:
case PointerUpdateKind.MiddleButtonReleased:
mouse = SKMouseButton.Middle;
break;
case PointerUpdateKind.XButton1Pressed:
case PointerUpdateKind.XButton1Released:
case PointerUpdateKind.XButton2Pressed:
case PointerUpdateKind.XButton2Released:
case PointerUpdateKind.Other:
default:
break;
}
return mouse;
}
}
}

Просмотреть файл

@ -44,6 +44,7 @@
<Compile Include="SKCanvasViewRenderer.cs" />
<Compile Include="SKGLViewRenderer.cs" />
<Compile Include="SKImageSourceHandler.cs" />
<Compile Include="SKTouchHandler.cs" />
<EmbeddedResource Include="Properties\SkiaSharp.Views.Forms.UWP.rd.xml" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -9,11 +9,15 @@ namespace SkiaSharp.Views.Forms
{
public class SKCanvasViewRenderer : SKCanvasViewRendererBase<SKFormsView, SKNativeView>
{
public SKCanvasViewRenderer()
{
SetDisablesUserInteraction(true);
}
protected override SKNativeView CreateNativeControl()
{
var view = base.CreateNativeControl();
view.UserInteractionEnabled = false;
// Force the opacity to false for consistency with the other platforms
view.Opaque = false;

Просмотреть файл

@ -13,11 +13,15 @@ namespace SkiaSharp.Views.Forms
{
private CADisplayLink displayLink;
public SKGLViewRenderer()
{
SetDisablesUserInteraction(true);
}
protected override SKNativeView CreateNativeControl()
{
var view = base.CreateNativeControl();
view.UserInteractionEnabled = false;
// Force the opacity to false for consistency with the other platforms
view.Opaque = false;

Просмотреть файл

@ -0,0 +1,107 @@
using System;
using System.Linq;
using Foundation;
using UIKit;
namespace SkiaSharp.Views.Forms
{
internal class SKTouchHandler : UIGestureRecognizer
{
private Action<SKTouchEventArgs> onTouchAction;
private Func<nfloat, nfloat> scalePixels;
public SKTouchHandler(Action<SKTouchEventArgs> onTouchAction, Func<nfloat, nfloat> scalePixels)
{
this.onTouchAction = onTouchAction;
this.scalePixels = scalePixels;
DisablesUserInteraction = false;
}
public bool DisablesUserInteraction { get; set; }
public void SetEnabled(UIView view, bool enableTouchEvents)
{
if (view != null)
{
if (!view.UserInteractionEnabled || DisablesUserInteraction)
{
view.UserInteractionEnabled = enableTouchEvents;
}
if (enableTouchEvents && view.GestureRecognizers?.Contains(this) != true)
{
view.AddGestureRecognizer(this);
}
else if (!enableTouchEvents && view.GestureRecognizers?.Contains(this) == true)
{
view.RemoveGestureRecognizer(this);
}
}
}
public void Detach(UIView view)
{
// clean the view
SetEnabled(view, false);
// remove references
onTouchAction = null;
scalePixels = null;
}
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
base.TouchesBegan(touches, evt);
foreach (UITouch touch in touches.Cast<UITouch>())
{
FireEvent(SKTouchAction.Pressed, touch, true);
}
}
public override void TouchesMoved(NSSet touches, UIEvent evt)
{
base.TouchesMoved(touches, evt);
foreach (UITouch touch in touches.Cast<UITouch>())
{
FireEvent(SKTouchAction.Moved, touch, true);
}
}
public override void TouchesEnded(NSSet touches, UIEvent evt)
{
base.TouchesEnded(touches, evt);
foreach (UITouch touch in touches.Cast<UITouch>())
{
FireEvent(SKTouchAction.Released, touch, false);
}
}
public override void TouchesCancelled(NSSet touches, UIEvent evt)
{
base.TouchesCancelled(touches, evt);
foreach (UITouch touch in touches.Cast<UITouch>())
{
FireEvent(SKTouchAction.Cancelled, touch, false);
}
}
private bool FireEvent(SKTouchAction actionType, UITouch touch, bool inContact)
{
if (onTouchAction == null || scalePixels == null)
return false;
var id = touch.Handle.ToInt64();
var cgPoint = touch.LocationInView(View);
var point = new SKPoint((float)scalePixels(cgPoint.X), (float)scalePixels(cgPoint.Y));
var args = new SKTouchEventArgs(id, actionType, point, inContact);
onTouchAction(args);
return args.Handled;
}
}
}

Просмотреть файл

@ -69,6 +69,7 @@
<Compile Include="SKGLViewRenderer.cs" />
<Compile Include="SKCanvasViewRenderer.cs" />
<Compile Include="SKImageSourceHandler.cs" />
<Compile Include="SKTouchHandler.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Binding\SkiaSharp.iOS\SkiaSharp.iOS.csproj">