Introduction to SkiaSharp
  1. SkiaSharp is a cross-platform 2D graphics API for .NET platforms.
  2. SkiaSharp Views & Layers is a set of platform-specific Views and Containers that can be used to draw on the screen and it's used in Google Chrome, Mozilla Firefox, and Android devices.
  3. Binding for Windows.Forms, WPF, iOS, tvOS, Mac, Android, Xamarin.Android and Xamarin.Forms and it can be used across mobile, server, and desktop models to render the images.
  4. Skia Graphics Engine was acquired by Google in 2005 and it's an open source package.
More details: github.com/mono/skiasharp

NuGet Package : Xamarin.Android -->search "SkiaSharp"

Xamarin.Forms -->search"SkiaSharp.Views.Forms"

Properties of SkiaSharp
  • SKcanvas.
  • SKGLView.
  • SKPaint.
  • SKPath.
  • SKShader.
  • SKPathEffect .
Now, let us discuss the attributes of SkiaSharp properties.

Drawing on SKcanvas

The SKcanvas is used for drawing models, lines, arcs, text, and images.

Drawing Methods of SKcanvas
  1. DrawCircle.
  2. DrawRect.
  3. DrawLine.
  4. DrawText.
  5. DrawBitmap.
  6. DrawPath.
Transforms for SKcanvas
  1. Translate.
  2. Scale.
  3. RotateDegrees.
  4. RotateRadians.
Drawing attributes for SKPaint
  1. Style: Storke, Fill, or both.
  2. Color: SKColor value.
  3. StrokeWidth.
  4. StrokeCap: Butt, Square, or Round.
  5. Strokejoin: Miter, Bevel, or Round.
  6. Shader: gradients or bitmap tilling.
SKPath --> Connected lines and curves
  1. MoveTo and LineTo.
  2. ArcTo: Three kinds of arc definitions.
  3. CubicTo and QuadTo: Bezier.
  4. SVG path date in and out.
SKShader --> Fancy filles
  1. CreateLinearGradient.
  2. CreateRadialGradient.
  3. CreateSweepGradient.
  4. CreateTwoPointConicalGradient.
  5. CreatePerlinNoise.
  6. CreateBitmap: Tile with SKBitmap.
SKPathEffects -->fancy strokes
  1. CreateDash.
  2. Create1DPathof: Dashed with another path.
  3. Create2DPath: Storked with an array of another path.
  4. CreateDiscrete: Jitter effect.
The below article contains just a few but many different things can be done by catclock with SkiaSharp.
Let's start.
Step 1

You can get started with a new Xamarin.Forms app by going to File >>New >>Visual C#>>Cross-platform >>select Cross-platform App(Xamarin.Native or Xamarin.Forms) and give the application a suitable name, such as CatClock. Choose your project location, then click OK.



Step 2

In this step, add the following NuGet Packages for your project.
  • SkiaSharp
  • SkiaSharp.Views
  • SkiaSharp.Views.Forms
For that, go to Solution Explorer and select your solution, right click and select "Manage NuGet Packages for the solution".
Now, select the following NuGet package and install it.
  • SkiaSharp.Views.Forms

Step 3

In this step, add a SkiaSharp control to your projects. For that, go to Solution Explorer >>catclock(PCL)>> double click on MainPage.xaml.

After opening this, you can add SkiaSharp assembly and XAML code to your project. Write the code given below.

Assembly
  1. xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
XAML Code
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  4. xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
  5. xmlns:local="clr-namespace:CatClock"
  6. x:Class="CatClock.MainPage">
  7. <ContentPage.Padding>
  8. <OnPlatform x:TypeArguments="Thickness"
  9. iOS="0, 20, 0, 0" />
  10. </ContentPage.Padding>
  11. <skia:SKCanvasView x:Name="canvasView"
  12. PaintSurface="canvasView_PaintSurface" />
  13. </ContentPage>
Step 4

Now, we need to add a picture for background display. For that, go to Solution Explorer >> Add >> Existing item >> select one picture and click OK.

After this, let's change the picture properties to embedded resource. For that, go to Properties window >> Advanced >> Build Action>>select Embedded Resource.

Step 5

In this step, open Solution Explorer>>catclock(PCL)>>Mainpage.xaml.cs page and double-click to open the design view. Here is the code for this page.
CS code
  1. using System;
  2. using System.IO;
  3. using System.Reflection;
  4. using Xamarin.Forms;
  5. using SkiaSharp;
  6. using SkiaSharp.Views.Forms;
  7. namespace CatClock
  8. {
  9. public partial class MainPage : ContentPage
  10. {
  11. SKPaint blackFillPaint = new SKPaint
  12. {
  13. Style = SKPaintStyle.Fill,
  14. Color = SKColors.Black
  15. };
  16. SKPaint whiteStrokePaint = new SKPaint
  17. {
  18. Style = SKPaintStyle.Stroke,
  19. Color = SKColors.White,
  20. StrokeWidth = 2,
  21. StrokeCap = SKStrokeCap.Round,
  22. IsAntialias = true
  23. };
  24. SKPaint whiteFillPaint = new SKPaint
  25. {
  26. Style = SKPaintStyle.Fill,
  27. Color = SKColors.White
  28. };
  29. SKPaint greenFillPaint = new SKPaint
  30. {
  31. Style = SKPaintStyle.Fill,
  32. Color = SKColors.PaleGreen
  33. };
  34. SKPaint blackStrokePaint = new SKPaint
  35. {
  36. Style = SKPaintStyle.Stroke,
  37. Color = SKColors.Black,
  38. StrokeWidth = 20,
  39. StrokeCap = SKStrokeCap.Round
  40. };
  41. SKPaint grayFillPaint = new SKPaint
  42. {
  43. Style = SKPaintStyle.Fill,
  44. Color = SKColors.Gray
  45. };
  46. SKPaint backgroundFillPaint = new SKPaint
  47. {
  48. Style = SKPaintStyle.Fill
  49. };
  50. SKPath catEarPath = new SKPath();
  51. SKPath catEyePath = new SKPath();
  52. SKPath catPupilPath = new SKPath();
  53. SKPath catTailPath = new SKPath();
  54. SKPath hourHandPath = SKPath.ParseSvgPathData(
  55. "M 0 -60 C 0 -30 20 -30 5 -20 L 5 0 C 5 7.5 -5 7.5 -5 0 L -5 -20 C -20 -30 0 -30 0 -60");
  56. SKPath minuteHandPath = SKPath.ParseSvgPathData(
  57. "M 0 -80 C 0 -75 0 -70 2.5 -60 L 2.5 0 C 2.5 5 -2.5 5 -2.5 0 L -2.5 -60 C 0 -70 0 -75 0 -80");
  58. public MainPage()
  59. {
  60. InitializeComponent();
  61. // Make cat ear path
  62. catEarPath.MoveTo(0, 0);
  63. catEarPath.LineTo(0, 75);
  64. catEarPath.LineTo(100, 75);
  65. catEarPath.Close();
  66. // Make cat eye path
  67. catEyePath.MoveTo(0, 0);
  68. catEyePath.ArcTo(50, 50, 0, SKPathArcSize.Small, SKPathDirection.Clockwise, 50, 0);
  69. catEyePath.ArcTo(50, 50, 0, SKPathArcSize.Small, SKPathDirection.Clockwise, 0, 0);
  70. catEyePath.Close();
  71. // Make eye pupil path
  72. catPupilPath.MoveTo(25, -5);
  73. catPupilPath.ArcTo(6, 6, 0, SKPathArcSize.Small, SKPathDirection.Clockwise, 25, 5);
  74. catPupilPath.ArcTo(6, 6, 0, SKPathArcSize.Small, SKPathDirection.Clockwise, 25, -5);
  75. catPupilPath.Close();
  76. // Make cat tail path
  77. catTailPath.MoveTo(0, 100);
  78. catTailPath.CubicTo(50, 200, 0, 250, -50, 200);
  79. // Create Shader
  80. Assembly assembly = GetType().GetTypeInfo().Assembly;
  81. using (Stream stream = assembly.GetManifestResourceStream("CatClock.WoodGrain.png"))
  82. using (SKManagedStream skStream = new SKManagedStream(stream))
  83. using (SKBitmap bitmap = SKBitmap.Decode(skStream))
  84. using (SKShader shader = SKShader.CreateBitmap(bitmap, SKShaderTileMode.Mirror, SKShaderTileMode.Mirror))
  85. {
  86. backgroundFillPaint.Shader = shader;
  87. }
  88. Device.StartTimer(TimeSpan.FromSeconds(1f / 60), () =>
  89. {
  90. canvasView.InvalidateSurface();
  91. return true;
  92. });
  93. }
  94. private void canvasView_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
  95. {
  96. SKSurface surface = e.Surface;
  97. SKCanvas canvas = surface.Canvas;
  98. canvas.DrawPaint(backgroundFillPaint);
  99. int width = e.Info.Width;
  100. int height = e.Info.Height;
  101. // Set transforms
  102. canvas.Translate(width / 2, height / 2);
  103. canvas.Scale(Math.Min(width / 210f, height / 520f));
  104. // Get DateTime
  105. DateTime dateTime = DateTime.Now;
  106. // Head
  107. canvas.DrawCircle(0, -160, 75, blackFillPaint);
  108. // Draw ears and eyes
  109. for (int i = 0; i < 2; i++)
  110. {
  111. canvas.Save();
  112. canvas.Scale(2 * i - 1, 1);
  113. canvas.Save();
  114. canvas.Translate(-65, -255);
  115. canvas.DrawPath(catEarPath, blackFillPaint);
  116. canvas.Restore();
  117. canvas.Save();
  118. canvas.Translate(10, -170);
  119. canvas.DrawPath(catEyePath, greenFillPaint);
  120. canvas.DrawPath(catPupilPath, blackFillPaint);
  121. canvas.Restore();
  122. // Draw whiskers
  123. canvas.DrawLine(10, -120, 100, -100, whiteStrokePaint);
  124. canvas.DrawLine(10, -125, 100, -120, whiteStrokePaint);
  125. canvas.DrawLine(10, -130, 100, -140, whiteStrokePaint);
  126. canvas.DrawLine(10, -135, 100, -160, whiteStrokePaint);
  127. canvas.Restore();
  128. }
  129. // Move Tail
  130. float t = (float)Math.Sin((dateTime.Second % 2 + dateTime.Millisecond / 1000.0) * Math.PI);
  131. catTailPath.Reset();
  132. catTailPath.MoveTo(0, 100);
  133. SKPoint point1 = new SKPoint(-50 * t, 200);
  134. SKPoint point2 = new SKPoint(0, 250 - Math.Abs(50 * t));
  135. SKPoint point3 = new SKPoint(50 * t, 250 - Math.Abs(75 * t));
  136. catTailPath.CubicTo(point1, point2, point3);
  137. canvas.DrawPath(catTailPath, blackStrokePaint);
  138. // Clock background
  139. canvas.DrawCircle(0, 0, 100, blackFillPaint);
  140. // Hour and minute marks
  141. for (int angle = 0; angle < 360; angle += 6)
  142. {
  143. canvas.DrawCircle(0, -90, angle % 30 == 0 ? 4 : 2, whiteFillPaint);
  144. canvas.RotateDegrees(6);
  145. }
  146. // Hour hand
  147. canvas.Save();
  148. canvas.RotateDegrees(30 * dateTime.Hour + dateTime.Minute / 2f);
  149. canvas.DrawPath(hourHandPath, grayFillPaint);
  150. canvas.DrawPath(hourHandPath, whiteStrokePaint);
  151. canvas.Restore();
  152. // Minute hand
  153. canvas.Save();
  154. canvas.RotateDegrees(6 * dateTime.Minute + dateTime.Second / 10f);
  155. canvas.DrawPath(minuteHandPath, grayFillPaint);
  156. canvas.DrawPath(minuteHandPath, whiteStrokePaint);
  157. canvas.Restore();
  158. // Second hand
  159. canvas.Save();
  160. float seconds = dateTime.Second + dateTime.Millisecond / 1000f;
  161. canvas.RotateDegrees(6 * seconds);
  162. whiteStrokePaint.StrokeWidth = 2;
  163. canvas.DrawLine(0, 10, 0, -80, whiteStrokePaint);
  164. canvas.Restore();
  165. }
  166. }
  167. }


Step 6

Now, go to "Build" menu and click "Configure Manager". Here, you can configure your startup projects. Click F5 or Start to build and run your application.
After a few seconds, the app will start running on your Android simulators and you will see your app working successfully.

Finally, we have successfully created a Xamarin.Forms catclock with SkiaSharp application.
Conclusion

I hope you have learned how to design cat clock application using Visual Studio.