Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.
This repository was archived by the owner on May 1, 2024. It is now read-only.

[Bug] Overwrite method touch on iOS native overlap by Touch Effect #14315

@iletai

Description

@iletai

Description

I had using Xamarin Form to custom my page with a custom Renderer.
And custom Touch with Touch Effect: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/effects/touch-tracking
When I enable my custom Render Native iOS. TouchBegan, Move, End just fire once on Native View. And after the event touch always fire from Touch Effect without fire Event on Native View myCustom. I try to detect something but seem Touch Effect is always top of the Main Page. Hit events method in UIView Custom still received events from my Native Custom UIView.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:tt="clr-namespace:Test.TouchTracking"
             xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms" xmlns:ext="clr-namespace:Test"
             x:Class="Test.MainPage">
      <Grid x:Name="MainPageGrid">
        <Grid.Effects>
            <tt:TouchEffect Capture="True" TouchAction="OnTouchEffectAction"/>
        </Grid.Effects>
        <skia:SKCanvasView x:Name="drawedFingerView" PaintSurface="drawed_PaintSurface" BackgroundColor="Yellow"/>
        <ContentView x:Name="contentViewTextParent" x:FieldModifier="public" HorizontalOptions="Center" BackgroundColor="AliceBlue"  VerticalOptions="CenterAndExpand">
            <ext:TestTouchFingerCanvas x:Name="TestFingerCanvas" HorizontalOptions="Fill" VerticalOptions="Fill"/>
        </ContentView>
      </Grid>
</ContentPage>

using System;
using CoreGraphics;
using Foundation;
using Test.iOS;
using Test.iOS.Views;

using Test;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using Test.TouchTracking;

[assembly: ExportRenderer(typeof(TestTouchFingerCanvas), typeof(FingerPaintCanvasRenderer))]

namespace Test.iOS.Views
{
   public class FingerPaintCanvasRenderer : ViewRenderer<TestTouchFingerCanvas, FingerPaintCanvasView>
   {
       public FingerPaintCanvasRenderer() : base()
       {
       }

       protected override void OnElementChanged(ElementChangedEventArgs<TestTouchFingerCanvas> e)
       {
           if (e.NewElement != null)
           {
               if (Control == null)
               {
                   var view = new FingerPaintCanvasView(UIScreen.MainScreen.Bounds);
                   SetNativeControl(view);
               }
               e.NewElement.TouchAction += OnTouchAction;
           }

           if (e.OldElement != null)
           {
               e.OldElement.TouchAction -= OnTouchAction;
           }
           base.OnElementChanged(e);
       }


       private void OnTouchAction(object sender, TouchActionEventArgs e)
       {
           if (null != Control)
           {
           }
       }

       protected override void Dispose(bool disposing)
       {
           base.Dispose(disposing);
       }

   }

}
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using CoreGraphics;
using Foundation;
using Test.iOS.Common;
using SkiaSharp;
using Test.iOS.Common;
using Test.TouchTracking;
using UIKit;

namespace Test.iOS
{
    public class FingerPaintCanvasView : UIView
    {
        Dictionary<IntPtr, FingerPaintPolyline> inProgressPolylines = new Dictionary<IntPtr, FingerPaintPolyline>();
        List<FingerPaintPolyline> completedPolylines = new List<FingerPaintPolyline>();
        Dictionary<IntPtr, CGPoint> inProgressFirstPoints = new Dictionary<IntPtr, CGPoint>();

        float haftSize = 0;
        bool actionErase = false;
        public static int MAX = 100;
        public float StrokeWidth;
        public static FingerPaintCanvasView Instance;
        public FingerPaintCanvasView() : base()
        {
            Instance = this;
        }

        public FingerPaintCanvasView(RectangleF frame) : base(frame)
        {
            Instance = this;
        }

        public FingerPaintCanvasView(CGRect rect) : base(rect)
        {
            Instance = this;
        }

        public object TouchObject { get; set; }

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

            foreach (UITouch touch in touches.Cast<UITouch>())
            {
                // Create a FingerPaintPolyline, set the initial point, and store it
                FingerPaintPolyline polyline = new FingerPaintPolyline
                {
                    Color = UIColor.Blue.CGColor,
                    StrokeWidth = StrokeWidth,
                };

                polyline.Path.MoveToPoint(touch.LocationInView(this));
                inProgressPolylines.Add(touch.Handle, polyline);
            }
            SetNeedsDisplay();
        }

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

            foreach (UITouch touch in touches.Cast<UITouch>())
            {
                // Add point to path
                inProgressPolylines[touch.Handle].Path.AddLineToPoint(touch.LocationInView(this));
            }
            SetNeedsDisplay();
        }

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

            foreach (UITouch touch in touches.Cast<UITouch>())
            {
                // Get polyline from dictionary and remove it from dictionary
                FingerPaintPolyline polyline = inProgressPolylines[touch.Handle];
                inProgressPolylines.Remove(touch.Handle);

                // Add final point to path and save with completed polylines
                polyline.Path.AddLineToPoint(touch.LocationInView(this));
                completedPolylines.Add(polyline);
            }
            SetNeedsDisplay();
        }

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

            foreach (UITouch touch in touches.Cast<UITouch>())
            {
                inProgressPolylines.Remove(touch.Handle);
            }
            SetNeedsDisplay();
        }

        public override void Draw(CGRect rect)
        {
            base.Draw(rect);

            using (CGContext context = UIGraphics.GetCurrentContext())
            {
                // Stroke settings
                context.SetLineCap(CGLineCap.Round);
                context.SetLineJoin(CGLineJoin.Round);

                // Draw the completed polylines
                foreach (FingerPaintPolyline polyline in completedPolylines)
                {
                    context.SetStrokeColor(UIColor.Blue.CGColor);
                    context.SetLineWidth(3);
                    context.AddPath(polyline.Path);
                    context.DrawPath(CGPathDrawingMode.Stroke);
                }

                // Draw the in-progress polylines
                foreach (FingerPaintPolyline polyline in inProgressPolylines.Values)
                {
                    context.SetStrokeColor(UIColor.Red.CGColor);
                    context.SetLineWidth(3);
                    context.AddPath(polyline.Path);
                    context.DrawPath(CGPathDrawingMode.Stroke);
                }
            }
        }
    }
}

Steps to Reproduce

  1. Custom Renderer for UI View on Xamarin Forms. Overwrite method touch relate on native UIVIew iOS
  2. Enable view content view to contain native uiview. Touch on it
  3. Event touch on TouchEffect was fire and touch on native was overlap

Expected Behavior

The only touch on native UI view was fire when it enables without Touch Effect fire events.

Actual Behavior

Touch Effect fire events

Basic Information

  • Version with issue: XamarinForms 5.3
  • Last known good version:
  • Platform Target Frameworks:
    • iOS: 14
  • NuGet Packages: SkiaCsharp, Xamarin Forms
  • Affected Devices: Real and Simulator iOS OS 14

Environment

Show/Hide Visual Studio info

Build Logs

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions