Skip to content

Commit

Permalink
Merge pull request #15 from RobertStefancic/oxy_zoom_fix_ios
Browse files Browse the repository at this point in the history
Fix: Zoom is not working on iOS
  • Loading branch information
janusw authored Sep 19, 2024
2 parents 707a12c + ef25e00 commit b9553ef
Showing 1 changed file with 26 additions and 101 deletions.
127 changes: 26 additions & 101 deletions Source/OxyPlot.Maui.Skia/Platforms/iOS/Effects/PlatformTouchEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,18 @@ namespace OxyPlot.Maui.Skia.ios.Effects;

public class PlatformTouchEffect : PlatformEffect
{
UIView view;
TouchRecognizer touchRecognizer;
private UIView view;
private TouchRecognizer touchRecognizer;

protected override void OnAttached()
{
// Get the iOS UIView corresponding to the Element that the effect is attached to
view = Control ?? Container;

// Uncomment this line if the UIView does not have touch enabled by default
//view.UserInteractionEnabled = true;

// Get access to the TouchEffect class in the .NET Standard library
var touchEffect = Element.Effects.OfType<MyTouchEffect>().FirstOrDefault();

if (touchEffect != null && view != null)
{
// Create a TouchRecognizer for this UIView
touchRecognizer = new TouchRecognizer(Element, view, touchEffect);
touchRecognizer = new TouchRecognizer(Element, touchEffect);
view.AddGestureRecognizer(touchRecognizer);
}
}
Expand All @@ -34,140 +28,71 @@ protected override void OnDetached()
{
if (touchRecognizer != null)
{
// Clean up the TouchRecognizer object
touchRecognizer.Detach();

// Remove the TouchRecognizer from the UIView
view.RemoveGestureRecognizer(touchRecognizer);
}
}
}

class TouchRecognizer : UIGestureRecognizer
internal class TouchRecognizer : UIGestureRecognizer
{
Microsoft.Maui.Controls.Element element; // Forms element for firing events
UIView view; // iOS UIView
MyTouchEffect touchPlatformEffect;

static Dictionary<UIView, TouchRecognizer> viewDictionary = new();
private readonly Microsoft.Maui.Controls.Element element;
private readonly MyTouchEffect touchEffect;
private uint activeTouchesCount = 0;

static Dictionary<long, TouchRecognizer> idToTouchDictionary = new();

public TouchRecognizer(Microsoft.Maui.Controls.Element element, UIView view, MyTouchEffect touchPlatformEffect)
public TouchRecognizer(Microsoft.Maui.Controls.Element element, MyTouchEffect touchEffect)
{
this.element = element;
this.view = view;
this.touchPlatformEffect = touchPlatformEffect;
this.touchEffect = touchEffect;

viewDictionary.Add(view, this);
ShouldRecognizeSimultaneously = new UIGesturesProbe((_, _) => true);
}

public void Detach()
{
viewDictionary.Remove(view);
ShouldRecognizeSimultaneously = null;
}

// touches = touches of interest; evt = all touches of type UITouch
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
base.TouchesBegan(touches, evt);

foreach (UITouch touch in touches.Cast<UITouch>())
{
long id = ((IntPtr)touch.Handle).ToInt64();
FireEvent(this, id, TouchActionType.Pressed, touch, true);

if (!idToTouchDictionary.ContainsKey(id))
{
idToTouchDictionary.Add(id, this);
}
}
activeTouchesCount += touches.Count.ToUInt32();
FireEvent(touches, TouchActionType.Pressed, true);
}

public override void TouchesMoved(NSSet touches, UIEvent evt)
{
base.TouchesMoved(touches, evt);

foreach (UITouch touch in touches.Cast<UITouch>())
if (activeTouchesCount == touches.Count.ToUInt32())
{
long id = ((IntPtr)touch.Handle).ToInt64();
CheckForBoundaryHop(touch);
if (idToTouchDictionary[id] != null)
{
FireEvent(idToTouchDictionary[id], id, TouchActionType.Moved, touch, true);
}
FireEvent(touches, TouchActionType.Moved, true);
}
}

public override void TouchesEnded(NSSet touches, UIEvent evt)
{
base.TouchesEnded(touches, evt);

foreach (UITouch touch in touches.Cast<UITouch>())
{
long id = ((IntPtr)touch.Handle).ToInt64();
CheckForBoundaryHop(touch);
if (idToTouchDictionary[id] != null)
{
FireEvent(idToTouchDictionary[id], id, TouchActionType.Released, touch, false);
}

idToTouchDictionary.Remove(id);
}
activeTouchesCount -= touches.Count.ToUInt32();
FireEvent(touches, TouchActionType.Released, false);
}

public override void TouchesCancelled(NSSet touches, UIEvent evt)
{
base.TouchesCancelled(touches, evt);

foreach (UITouch touch in touches.Cast<UITouch>())
{
long id = ((IntPtr)touch.Handle).ToInt64();
idToTouchDictionary.Remove(id);
}
}

void CheckForBoundaryHop(UITouch touch)
private void FireEvent(NSSet touches, TouchActionType actionType, bool isInContact)
{
long id = ((IntPtr)touch.Handle).ToInt64();

// TODO: Might require converting to a List for multiple hits
TouchRecognizer recognizerHit = null;
UITouch[] uiTouches = touches.Cast<UITouch>().ToArray();
long id = ((IntPtr)uiTouches.First().Handle).ToInt64();
Point[] points = new Point[uiTouches.Length];

foreach (UIView view in viewDictionary.Keys)
{
CGPoint location = touch.LocationInView(view);

if (new CGRect(new CGPoint(), view.Frame.Size).Contains(location))
{
recognizerHit = viewDictionary[view];
}
}
if (recognizerHit != idToTouchDictionary[id])
for (int i = 0; i < uiTouches.Length; i++)
{
if (idToTouchDictionary[id] != null)
{
FireEvent(idToTouchDictionary[id], id, TouchActionType.Pressed, touch, true);
}
if (recognizerHit != null)
{
FireEvent(recognizerHit, id, TouchActionType.Released, touch, true);
}
idToTouchDictionary[id] = recognizerHit;
CGPoint cgPoint = uiTouches[i].LocationInView(View);
points[i] = new(cgPoint.X, cgPoint.Y);
}
touchEffect.OnTouchAction(element, new(id, actionType, points, isInContact));
}

void FireEvent(TouchRecognizer recognizer, long id, TouchActionType actionType, UITouch touch, bool isInContact)
{
// Convert touch location to Maui Point value
CGPoint cgPoint = touch.LocationInView(recognizer.View);
Point xfPoint = new Point(cgPoint.X, cgPoint.Y);

// Get the method to call for firing events
var onTouchAction = recognizer.touchPlatformEffect.OnTouchAction;

// Call that method
onTouchAction(recognizer.element,
new TouchActionEventArgs(id, actionType, new[] { xfPoint }, isInContact));
}
}
}

0 comments on commit b9553ef

Please sign in to comment.