Is there a way to access a SKSurface outside of the PaintSurface event?

All of the code examples I've seen on the subject access the Skia Canvas by defining a "PaintSurface" event in the XAML of a SKCanvasView and accessing the surface and the canvas via. the event handlers' passed arguments.

What I'm looking for is a way to access the SKSurface by demand and not just when the canvas is painted.

For instance - I want to have a page with a Canvas which paints something and a button, which, when pressed - will access the SKSurface and save the current painting via the "SnapShot()" method.
The problem is that I don't have access to the active SKSurface when handling the 'save' button click, since that is retreived only when the paint event is handled.

I tried holding a global SKSurface variable that is assigned the value given whenever the paint event is handeled, but that didn't work too, since the Application crashed completely when I tried calling it's Snapshot() method.

Are there any other ways of obtaining and using the active SKSurface from outside of the PaintSurface event?

Thank you.

Best Answer

Answers

  • mattleibowmattleibow ZAXamarin Team Xamurai
    edited July 2017

    The way SkiaSharp works is to get the surface from the OS, and then make it available to you in the paint event. On many OSes, this surface only lives as long as the paint event, so there is no way to preserve it. If you need to draw to a surface arbitrarily, you will need to create your own. This is easy:

    // create the bitmap that we can access
    var bitmap = new SKBitmap(width, height);
    
    // create a canvas so we can draw
    var canvas = new SKCanvas(bitmap);
    
    // ... draw whenever we need to ...
    canvas.Clear();
    canvas.DrawXXX
    

    Then, in the paint method, we can just draw the bitmap:

    private void OnPainting(object sender, SKPaintSurfaceEventArgs e)
    {
        e.Surface.Canvas.DrawBitmap(bitmap, 0, 0);
    }
    

    This way we always have access to the bitmap, but also display it on the screen.

  • EladZEladZ USMember

    Thanks, that's a nice approach.

    The problem would be mainly that if previously I had flexibilty on the canvas size as dependent on the CanvasView control, which could have changed size throughout the application, I now have to initialize the bitmap's canvas with constant sizes. So I have to assume that the canvas size doesn't change throught the application's lifetime.

    Another thing that bugs me is that in order to use and paint the Canvas (which is available only via handleing the 'PaintSurface' event) has to be done in code-behind. So if I wanted to use MVVM and have my drawable objects with their logic in the ViewModel, it is hard to connect between the two without breaking the MVVM pattern. Is there any way to overcome this?

    Thank you.

  • EladZEladZ USMember

    Thanks ! will check that out.

Sign In or Register to comment.