SkiaSharp icon indicating copy to clipboard operation
SkiaSharp copied to clipboard

In the OnTouch an event is missing when the FlyOut is opened

Open pauldendulk opened this issue 1 year ago • 2 comments

Description

When a FlyOut is opened on iOS there is no event to indicate a loss of touch. On Android an SKTouchAction.Cancelled is called, but on iOS no event at all.

Why is this a problem? The OnTouch event only gives information about single finger presses. We need to track those to know how many fingers are pressed. If an event is missing there is no way to correct for that. We have to assume it is still touching.

Expected Behavior

The same behavior as on Android, a SKTouchAction.Cancelled ActionType OnTouch event

Actual Behavior

No event

Basic Information

  • Version with issue: 2.88.3
  • Last known good version: Not known
  • Platform Target Frameworks:
    • iOS: maui-ios 7.0.86/7.0.100
  • Target Devices: Tested on Device - iPhone Pro Max 14 (physical device) and some others

pauldendulk avatar Jun 16 '23 05:06 pauldendulk

I attempted to recreate a minimal reproducible sample but seeing that only the SKTouchAction.Pressed event is firing on iOS. On Windows, I am seeing other ActionTypes, not just Pressed.

Repo - https://github.com/nm4568/SkiaSharpSamples

XAML

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:skia="clr-namespace:SkiaSharp.Views.Maui.Controls;assembly=SkiaSharp.Views.Maui.Controls"
             x:Class="SkiaSharpSample.MainPage">
<StackLayout>
        <skia:SKCanvasView x:Name="skCanvasView" PaintSurface="View_PaintSurface" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
        <Label x:Name="DebugLabel"
               FontSize="20"
               HorizontalOptions="Center"
               VerticalOptions="End" />
    </StackLayout>
</ContentPage>

C#

using SkiaSharp;
using SkiaSharp.Views.Maui;
using SKCanvasView = SkiaSharp.Views.Maui.Controls.SKCanvasView;

namespace SkiaSharpSample
{
    public partial class MainPage : ContentPage
    {
        SKBitmap skBitmap;

        public MainPage()
        {
            InitializeComponent();

            skCanvasView.EnableTouchEvents = true;
            skCanvasView.PaintSurface += View_PaintSurface;
            skCanvasView.Touch += SkCanvasView_Touch;
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();

            // Load and render a PNG image using SkiaSharp
            RenderSkiaSharpImage();
        }

        private void RenderSkiaSharpImage()
        {
            // Get the stream of the embedded resource
            var stream = typeof(MainPage).Assembly.GetManifestResourceStream("SkiaSharpSample.Resources.Images.dotnet_bot.png");

            // Create a SKBitmap from the stream
            skBitmap = SKBitmap.Decode(stream);

        }

        private void SkCanvasView_Touch(object? sender, SkiaSharp.Views.Maui.SKTouchEventArgs e)
        {
            switch (e.ActionType)
            {
                case SKTouchAction.Entered:
                    DebugLabel.Text = "Entered";
                    break;
                case SKTouchAction.Pressed:
                    DebugLabel.Text = "Pressed";
                    break;
                case SKTouchAction.Moved:
                    DebugLabel.Text = "Moved";
                    break;
                case SKTouchAction.Released:
                    DebugLabel.Text = "Released";
                    break;
                case SKTouchAction.Cancelled:
                    DebugLabel.Text = "Canceled";
                    break;
                case SKTouchAction.Exited:
                    DebugLabel.Text = "Exited";
                    break;
            }

            // Invalidate the canvas to trigger a redraw
            ((SKCanvasView)sender).InvalidateSurface();
        }

        private void View_PaintSurface(object? sender, SkiaSharp.Views.Maui.SKPaintSurfaceEventArgs e)
        {
            // Get the SKCanvas from the event arguments
            var canvas = e.Surface.Canvas;

            // Clear the canvas
            canvas.Clear(SKColors.White);

            // Draw the SKBitmap onto the canvas
            canvas.DrawBitmap(skBitmap, new SKPoint(0, 0));
        }
    }
}

nm4568 avatar Jan 07 '24 03:01 nm4568

@mattleibow Could you take a look at this? A minimal reproducible sample was added @nm4568 so it should be easy to reproduce. In Mapsui we need to keep track of the number of fingers touching the map. In some scenarios there is no way for use to find out that a finger is not touching anymore.

pauldendulk avatar Jan 07 '24 08:01 pauldendulk