Sample with SkiaSharp

In this tutorial we'll see how integrate SkiaSharp drawing inside a ReactorUI component. Let's first install ReactorUI SkiaSharp binding package:

Install-Package XamarinReactorUI.Skia

XamarinReactorUI.Skia package provides two classes: RxSKCanvasView and RxSKGLView. They can be used to integrate SkiaSharp backends in a component.

Let's create a sample empty page:

public class MainPage : RxComponent
{
    public override VisualNode Render()
    {
        return new RxContentPage()
        {
        };
    }
}

To draw some graphics we just need to create a RxSKCanvasView and handle the OnPaintSurfacecallback (sample drawing code is freely copied from Xamarin doc):

    public class MainPageState : IState
    { 
        public double RotationAngle { get; set; }
    }

    public class MainPage : RxComponent<MainPageState>
    {
        public override VisualNode Render()
        {
            return new RxContentPage()
            {
                new RxSKCanvasView()
                    .OnPaintSurface(OnPaintCanvasSurface)
            };
        }

        private void OnPaintCanvasSurface(SKPaintSurfaceEventArgs args)
        {
            SKImageInfo info = args.Info;
            SKSurface surface = args.Surface;
            SKCanvas canvas = surface.Canvas;

            canvas.Clear();

            string text = "OUTLINE";

            // Create an SKPaint object to display the text
            SKPaint textPaint = new SKPaint
            {
                Style = SKPaintStyle.Stroke,
                StrokeWidth = 1,
                FakeBoldText = true,
                Color = SKColors.Blue
            };

            // Adjust TextSize property so text is 95% of screen width
            float textWidth = textPaint.MeasureText(text);
            textPaint.TextSize = 0.95f * info.Width * textPaint.TextSize / textWidth;

            // Find the text bounds
            SKRect textBounds = new SKRect();
            textPaint.MeasureText(text, ref textBounds);

            // Calculate offsets to center the text on the screen
            float xText = info.Width / 2 - textBounds.MidX;
            float yText = info.Height / 2 - textBounds.MidY;

            // And draw the text
            canvas.DrawText(text, xText, yText, textPaint);
        }
    }

If you run the app you should something like this:

Now let's add some interactivity: for example adding the ability to rotate the text. We need a state that hold the current rotation angle, a slider to allow user modify this value, finally we need to invalidate SkiaSharp canvas when angle changes:

    public class MainPageState : IState
    { 
        public double RotationAngle { get; set; }
    }

    public class MainPage : RxComponent<MainPageState>
    {
        private SKCanvasView _canvasView;

        public override VisualNode Render()
        {
            return new RxContentPage()
            {
                new RxStackLayout()
                {
                    new RxLabel("Rotation Angle"),
                    new RxSlider()
                        .Minimum(0)
                        .Maximum(360.0)
                        .Value(State.RotationAngle)
                        .OnValueChanged(v => SetState(s =>
                        {
                            s.RotationAngle = v.NewValue;
                            _canvasView.InvalidateSurface();
                        }))
                        .HFill()
                        .VStart(),
                    new RxSKCanvasView(canvasView => _canvasView = canvasView)
                        .OnPaintSurface(OnPaintCanvasSurface)
                        .VFillAndExpand()
                }
            };
        }

        private void OnPaintCanvasSurface(SKPaintSurfaceEventArgs args)
        {
            .... omitted for brevity ....

            // And draw the text
            canvas.RotateDegrees((float)State.RotationAngle, info.Width / 2, info.Height / 2);
            canvas.DrawText(text, xText, yText, textPaint);
        }
    }

Following is the app as it should work now:

Last updated