Hi techies, this is another quick post about SkiaSharp and this little control made with it.
When I published a post about SkiaSharp (you can check it out here) some people told me whether or not I could make this progress bar editable, so a user can click and update the progress. So let's do it and reviewing how SkiaSharp handles touch events.
If you prefer to check the code directly you could go directly to the repository on Github https://github.com/jesulink2514/XamBooksApp/tree/feature/touch-progress
Let's do it
Ok, to begin with, we must provide a constructor to our control and enable touch events in SkiaSharp, easy.
public class GradientProgressBar: SKCanvasView
EnableTouchEvents = true;
In order to calculate the percentage based on touch position, I need a scale factor to convert between Xamarin.Forms units and SkiaSharp units (kind of pixel unit) so I defined a protected float field called
protected float ScaleFactor;
I've been calculating this factor in
OnPaintSurface so I just need to set this value to our
protected override void OnPaintSurface(SKPaintSurfaceEventArgs e)
var info = e.Info;
var canvas = e.Surface.Canvas;
float width = (float)Width;
var scale = CanvasSize.Width / width;
ScaleFactor = scale;
With all this plumbing in place (not much to be honest), I can show you the magic. I should override the
OnTouch method in order to process touch events. This method receives an instance of
SKTouchEventArgs that give us all information available about this interaction.
I interested in handling changes while users are still touching the progress bar, not only at the start of interaction or the end, so I handled
SKTouchAction.Moved. You can check more detail about this enum here.
Then, I must calculate the new percentage in our progress bar considering touch position, for this our
SKTouchEventArgs instance (e) provides me with
Location property and
Thinking about math here, if I know 100% width and current x value, based on the rule of 3, the percentage would be equal to current x value divided by 100% width value.
I like to add this
Math.Max for the percentage to avoid values falling behind zero and this
Location.X to avoid values going further than 100%.
And the final touch (=D funny if you caught it), is the
e.Handled = true, to avoid event bubbling.
And that's it, our control receives touch input to set percentage if you required.
PD: You can turn off this behaviour just setting this control to disabled (
Enabled=false on XAML or code).