Hi all,
I am currently looking at the SkiaSharp Example here: https://developer.xamarin.com/guides/cross-platform/drawing/introduction/#Obtaining_an_SKCanvas.
It seem's easy enough and i implemented my code as the following:
public TestController() { InitializeComponent(); DrawXamagon(); } protected void DrawXamagon() { using (var surface = SKSurface.Create(width: 640, height: 480, colorType:SKColorType.Rgb565, alphaType: SKAlphaType.Premul)) { SKCanvas canvas = surface.Canvas; // clear the canvas / fill with white canvas.Clear(SKColors.White); // set up drawing tools using (var paint = new SKPaint()) { paint.IsAntialias = true; paint.Color = new SKColor(0x2c, 0x3e, 0x50); paint.StrokeCap = SKStrokeCap.Round; // create the Xamagon path using (var path = new SKPath()) { path.MoveTo(71.4311121f, 56f); path.CubicTo(68.6763107f, 56.0058575f, 65.9796704f, 57.5737917f, 64.5928855f, 59.965729f); path.LineTo(43.0238921f, 97.5342563f); path.CubicTo(41.6587026f, 99.9325978f, 41.6587026f, 103.067402f, 43.0238921f, 105.465744f); path.LineTo(64.5928855f, 143.034271f); path.CubicTo(65.9798162f, 145.426228f, 68.6763107f, 146.994582f, 71.4311121f, 147f); path.LineTo(114.568946f, 147f); path.CubicTo(117.323748f, 146.994143f, 120.020241f, 145.426228f, 121.407172f, 143.034271f); path.LineTo(142.976161f, 105.465744f); path.CubicTo(144.34135f, 103.067402f, 144.341209f, 99.9325978f, 142.976161f, 97.5342563f); path.LineTo(121.407172f, 59.965729f); path.CubicTo(120.020241f, 57.5737917f, 117.323748f, 56.0054182f, 114.568946f, 56f); path.LineTo(71.4311121f, 4056f); path.Close(); // draw the Xamagon path canvas.DrawPath(path, paint); } } }
I have no errors and the code steps through fine, but noting is displayed (It should display the Xamarin logo). There dosen't seem to be much more to the example, am i supposed to initialise a canvas or Skview in the XAML, or is there any mistakes anybody can see in my example?
Thank you in advanced.
@ConorMurphy Thanks for trying out SkiaSharp. I just pushed out some new updates to SkiaSharp and added a few new features. The docs are a bit behind, so I would suggest using the new SkiaSharp.Views or SkiaSharp.Views.Forms NuGets. These NuGets provided a ready-to-use set of views that you can make use of right away. Also, the samples have been updated, with a far simpler structure.
You will be able to do something like this:
SKCanvasView myView = new SKCanvasView(); myView.PaintSurface += (sender, e) => { var canvas = e.Surface.Canvas; // ... }
If you don't want to use events, you can override the DrawInSurface
method on iOS, or the equivalent on the other platforms. If you are using Xamarin.Forms, try out the new SkiaSharp.Views.Forms and you can just drop those in.
There is also the SKGLView
which provides the same API, but instead is GPU powered. It uses OpenGL on all the platforms, and DirectX on Windows UWP.
About your specific problem, the reason nothing is being draw is because you are not drawing the surface to your view. a SKSurface
is really just an in-memory bitmap. You then you have to blit/draw that onto your view.
Answers
@ConorMurphy Thanks for trying out SkiaSharp. I just pushed out some new updates to SkiaSharp and added a few new features. The docs are a bit behind, so I would suggest using the new SkiaSharp.Views or SkiaSharp.Views.Forms NuGets. These NuGets provided a ready-to-use set of views that you can make use of right away. Also, the samples have been updated, with a far simpler structure.
You will be able to do something like this:
If you don't want to use events, you can override the
DrawInSurface
method on iOS, or the equivalent on the other platforms. If you are using Xamarin.Forms, try out the new SkiaSharp.Views.Forms and you can just drop those in.There is also the
SKGLView
which provides the same API, but instead is GPU powered. It uses OpenGL on all the platforms, and DirectX on Windows UWP.About your specific problem, the reason nothing is being draw is because you are not drawing the surface to your view. a
SKSurface
is really just an in-memory bitmap. You then you have to blit/draw that onto your view.@mattleibow Thanks for the reply, after posting this I came across your update 1.54 with the SkiaSharp.Views implementation.
After following the samples in the project I used the:
"views:SKCanvasView x:Name="canvas" PaintSurface="OnPaint"
code to complete my logic.
All is working great now and the library is pretty awesome.
Thanks!
@ConorMurphy Great to hear that this helps!
This might also be useful - rather than drawing the image each time, you can cache it like here: http://forums.xamarin.com/discussion/comment/228107/#Comment_228107
Hello Matthew, I've tried to use the library but I keep getting an error when running the app:
System.InvalidCastException: Specified cast is not valid.
This as soon as the page is load. The xaml is pretty basic, I'm just trying to display it :
<StackLayout HeightRequest="400" WidthRequest="400"> <views:SKCanvasView x:Name="CanvasView" PaintSurface="OnPaintCanvas" WidthRequest="400" HeightRequest="400" /> </StackLayout>
Finally the code behind is exactly the same as Conor's
private void OnPaintCanvas(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs e) { // Code for Drawing a Xamarin logo }
I don't know how useful is it, but this is the Call Stack:
> 0x1B in Xamarin.Forms.Registrar<Xamarin.Forms.IRegisterable>.GetHandler at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Core\Registrar.cs:24,4 C# 0x2 in Xamarin.Forms.Registrar<Xamarin.Forms.IRegisterable>.GetHandler<Xamarin.Forms.Platform.Android.IVisualElementRenderer> at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Core\Registrar.cs:29,4 C# 0x11 in Xamarin.Forms.Platform.Android.Platform.CreateRenderer at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:288,4 C# 0x24 in Xamarin.Forms.Platform.Android.VisualElementPackager.AddChild at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:74,5 C# 0x116 in Xamarin.Forms.Platform.Android.VisualElementPackager.SetElement at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:207,6 C# 0xD in Xamarin.Forms.Platform.Android.VisualElementPackager.Load at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:58,4 C# 0x8 in Xamarin.Forms.Platform.Android.VisualElementRenderer<Xamarin.Forms.View>.SetPackager at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:334,4 C# 0x118 in Xamarin.Forms.Platform.Android.VisualElementRenderer<Xamarin.Forms.View>.SetElement at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:193,5 C# 0x2E in Xamarin.Forms.Platform.Android.VisualElementRenderer<Xamarin.Forms.View>.Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:126,4 C# 0x21 in Xamarin.Forms.Platform.Android.Platform.CreateRenderer at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:289,4 C# 0x24 in Xamarin.Forms.Platform.Android.VisualElementPackager.AddChild at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:74,5 C# 0x116 in Xamarin.Forms.Platform.Android.VisualElementPackager.SetElement at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:207,6 C# 0xD in Xamarin.Forms.Platform.Android.VisualElementPackager.Load at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:58,4 C# 0x8 in Xamarin.Forms.Platform.Android.VisualElementRenderer<Xamarin.Forms.Page>.SetPackager at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:334,4 C# 0x118 in Xamarin.Forms.Platform.Android.VisualElementRenderer<Xamarin.Forms.Page>.SetElement at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:193,5 C# 0x2E in Xamarin.Forms.Platform.Android.VisualElementRenderer<Xamarin.Forms.Page>.Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:126,4 C# 0x33 in Xamarin.Forms.Platform.Android.Platform.CreateRenderer at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:325,4 C# 0x15 in Xamarin.Forms.Platform.Android.AppCompat.FragmentContainer.OnCreateView at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\AppCompat\FragmentContainer.cs:66,5 C# 0x12 in Android.App.Activity.OnStart at /Users/builder/data/lanes/3819/96c7ba6c/source/monodroid/src/Mono.Android/platforms/android-24/src/generated/Android.App.Activity.cs:4378,5 C# 0x1 in Xamarin.Forms.Platform.Android.FormsAppCompatActivity.OnStart at C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\AppCompat\FormsAppCompatActivity.cs:265,4 C# 0xA in Android.App.Activity.n_OnStart at /Users/builder/data/lanes/3819/96c7ba6c/source/monodroid/src/Mono.Android/platforms/android-24/src/generated/Android.App.Activity.cs:4368,4 C#
@AlejandroCons, just want to check. Did you install the SkiaSharp.Views.Forms in the app project as well?
@mattleibow Just an FYI, if I use a SKGLView my drawing is...hosed...lots of random gray dots / black squares. Also, I draw the same thing 5 times side-by-side right now, but each drawing comes out different using SKGLView. If I switch back to SKCanvasView it all works as expected. This is on an actual/real android s5.
It may be Android issues. I use a Nexus 5 for testing and things work most of the times, but I have artifacts in some cases
. Are you able to run the samples? (make sure to use the v1.54.1 release) The Android Xamarin.Forms app woks OK for me. You need to switch to the GL backend using the gear on the Toolbar.
If the sample works for you, then maybe your GL context is not being set up correctly in your app. If that is broken, then I will see what I can do about testing on an Android S5. I'll run a test on TestCloud and see what happens.
@Beachside_Jason, another thing might be how I set up my context. I use this:
SetEGLConfigChooser(8, 8, 8, 8, 0, 8);
, which is 8 bits for the RGBA, 0 depth and 8 for stencil size. It is also using OpenGLES 2.0.Also, what version of Android are you running?
@mattleibow Of all your questions I can only answer one, I'm running on Android 6.0 API Level 23. I tried downloading the samples from GitHub and opened up SkiaSharp-master/samples/FormsSample/FormsSample.sln but it failed to compile for me. It looks like references to SkiaSharp, SkiaSharp.Svg, SkiaSharp.Views.Android, and SkiSharp.View.Forms failed to resolve even though I did a nuget package restore. Maybe I have to open up and build other solutions locally. I've only just started to dabble in C# and Xamarin so I'm not terribly versed at working through these issues yet. I do have my source code available here. I also wasn't able to reference GLSurfaceView from my PCL and while I can reference it from my android project
MainActivity, GLSurfaceView.SetEGLConfigChooser
isn't a static method so I didn't see how to make that call from there and I didn't see the FormsSample android project doing that, so I didn't have an example to follow.@mattleibow I should mention I'm perfectly content using SKCanvasView
I too got the error System.InvalidCastException: Specified cast is not valid.
To resolve it I reinstalled the nuget packages for SkiaSharp, ShiaSharp.Views and SkiaSharp.Views.Forms.
I think the problem was that I hadn't selected to install the packages across ALL projects in my solutions only the portable project. Don't forget to restart Visual Studio too. I hope that helps someone.
@JohnWesterman Hi John, yes, this was helping me! I had the Skia packages only installed in the portable project. After adding to the other ones the error has vanished. Thx!
Hi everyone,
I have the same exception InvalidCastException when I try to add an SKCanvasView inside an AbsoluteLayout because xamarin forms because is unable to cast type SkiaSharp.Views.Forms.SKCanvasViewRenderer on type Xamarin.Forms.IRegisterable.
I use Xamarin.Forms 3.0-pre3 (I know is a prerelease.. maybe is because of that) in a WPF project with SkiaSharp 1.60.0