Коммит
13fd5bc765
|
@ -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">
|
||||
|
|
Загрузка…
Ссылка в новой задаче