GradientProgressBar: Accepting touch input Skiasharp
- 3 min read
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.
TL;DR;
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 { public GradientProgressBar() { 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 ScaleFactor
;
protected float ScaleFactor;
I’ve been calculating this factor in OnPaintSurface
so I just need to set this value to our ScaleFactor
field.
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.Pressed
, SKTouchAction.Released
and 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 X
value.
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 Math.Min
for 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).
https://github.com/jesulink2514/XamBooksApp/tree/feature/touch-progress