Search code examples
xamarinxamarin.formstouchskiasharp

Why does SkiaSharp Touch SKTouchAction.Moved event not work?


Summary

The Touch event is never raised with the ActionType of SKTouchAction.Moved, but SKTouchAction.Pressed is raised. Why does the .Moved event never get raised?

Detail

I am attempting to create a slider in SkiaSharp. This control will need to update the thumb (the little movable circle) when the user either touches on the slider or drags. This is hosted in a Xamarin Forms app, and I have created a SKCanvasView to draw the slider and to respond to touch events.

I have successfully responded to touch events, so I know the SKCanvasView is receiving some UI events, but the SKTouchAction.Moved is never raised.

Example Code

private SKCanvasView CreateSliderControl()
{
    var control = new SKCanvasView();
    control.PaintSurface += HandlePaintHeightControl;
    control.EnableTouchEvents = true;
    control.Touch += (sender, args) =>
    {
        var pt = args.Location;

        switch (args.ActionType)
        {
            case SKTouchAction.Pressed:
                // 1. This code gets hit whenever I touch the canvas
                control.InvalidateSurface();
                break;
            case SKTouchAction.Moved:
                // 2. This code never gets hit, even if I push, touch, slide, etc
                control.InvalidateSurface();
                break;
        }
    };
    control.InputTransparent = false;

    return control;
}

As shown above #1 gets hit (I can put a breakpoint there, and my control surface is invalidated). #2 never gets hit ever, but I expect it to get hit when I slide my finger over the control.

What I've Tried


Solution

  • Found a similar issue on SkiaSharp's Github.

    Try telling the OS that you want to "continue receiving touch events" by setting the Handled property in the event's args to true.

    private SKCanvasView CreateSliderControl()
    {
        var control = new SKCanvasView();
        control.PaintSurface += HandlePaintHeightControl;
        control.EnableTouchEvents = true;
        control.Touch += (sender, args) =>
        {
            var pt = args.Location;
    
            switch (args.ActionType)
            {
                case SKTouchAction.Pressed:
                    control.InvalidateSurface();
                    break;
                case SKTouchAction.Moved:
                    control.InvalidateSurface();
                    break;
            }
            // Let the OS know that we want to receive more touch events
            args.Handled = true;
        };
        control.InputTransparent = false;
    
        return control;
    }