概要
Xamarin.Formsを使うとマルチプラットフォーム向けアプリのUI実装が共通化できるのだが、デフォルトではボタンやテキストボックス等、必要最低限なコントロールしか用意されていない。
ちょっと凝ったことをしたい場合、例えば描画処理を自分で実装しようと思ったら各プラットフォームごとに書くしかないのである。
しかし、せっかくXamarinを使うのだったら、なるべくコードは共通化したい。
そこで、SkiaSharpというライブラリを使ってPCL側で描画処理を実装するようにしてみる。
環境
macOS Sierra
Visual Studio Community 2017 for Mac
準備
Visual Studioを起動し、新しいソリューションを作成する。
ここでは、ソリューション名を「HelloSkia」とした。プロジェクトのテンプレートは
Multiplatform -> アプリ -> Xamarin.Forms -> Blank Forms App
を選択する。
ソリューションが作成されると、中にPCL, Android向け, iOS向けのプロジェクトができているので、
すべてのプロジェクトに必要なパッケージを追加する。今回は、
プロジェクトを右クリック -> 追加 -> NuGetパッケージの追加でSkiaSharp for Xamarin.Formsを選ぶ。
この時点で、PCLプロジェクトにはSkiaSharp, SkiaSharp.Views.Forms, AndroidとiOSプロジェクトにはSkiaSharp, SkiaSharp.Views, SkiaSharp.View.Formsのパッケージが追加されていればよい。
実装
xamlの実装
HelloSkiaという名前でソリューションを作成した場合、PCLプロジェクトにHelloSkiaPage.xamlというファイルが生成されているはずである。まずは、このファイルを編集する。
HelloSkiaPage.xaml
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloSkia"
xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
x:Class="HelloSkia.HelloSkiaPage">
<StackLayout VerticalOptions="FillAndExpand">
<Label Text="Welcome to Xamarin Forms!" VerticalOptions="Center" HorizontalOptions="Center" />
<skia:SKCanvasView x:Name="canvasView" PaintSurface="Handle_PaintSurface" HeightRequest="400" />
</StackLayout>
</ContentPage>
注目するのはハイライトした部分である。
xmlns:skia=”clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms”
として、以降skia:という名前でSkiaSharpのクラスにアクセスできるようにする。
そして、StackLayoutに1つのSKCanvasViewを追加している。SKCanvasViewはカスタムの描画処理を実装できるViewで、Xamarin.Formsの他のViewと同じようにレイアウトに含めたりできる。
このタグの中にあるPaintSurfaceというのはSKCanvasViewの描画イベントである。
ここにHandle_PaintSurfaceというメソッド名を指定している。このようにすると描画が要求されたタイミングでこのメソッドが呼ばれるようになる。
コードビハインドの実装
次にコードビハインドを実装していこう。xamlがHelloSkiaPage.xamlという名前であれば、コードビハインドのファイルはHelloSkiaPage.xaml.csという名前でHelloSkiaPage.xamlの一階層下にあるはずである。実装内容は以下のようにした。
HelloSkiaPage.xaml.cs
using SkiaSharp;
using Xamarin.Forms;
namespace HelloSkia
{
public partial class HelloSkiaPage : ContentPage
{
private SKPaint rectPaint = new SKPaint
{
StrokeWidth = 4,
IsAntialias = true,
Color = SKColors.Blue
};
private SKPaint circlePaint = new SKPaint
{
StrokeWidth = 4,
IsAntialias = true,
Color = SKColors.Green
};
private SKPaint linePaint = new SKPaint
{
StrokeWidth = 4,
IsAntialias = true,
Color = SKColors.Red
};
public HelloSkiaPage()
{
InitializeComponent();
}
// 描画メソッド。
void Handle_PaintSurface(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs e)
{
var canvas = e.Surface.Canvas;
// 四角形を描画
canvas.DrawRect(new SKRect(10, 10, 200, 200), rectPaint);
// 円を描画
canvas.DrawCircle(320, 110, 100, circlePaint);
// 線を描画
canvas.DrawLine(430, 10, 630, 210, linePaint);
canvas.DrawLine(630, 10, 430, 210, linePaint);
}
}
}
描画処理は先ほどのxamlで指定しておいたHandle_PaintSurfaceメソッドに書いて行く。
ここでは、四角形、円、ラインといった簡単な図形を描画してみた。APIの使い方は、AndroidでonDrawを実装するときとほぼ一緒という感覚である。
これを各プラットフォームのシミュレータで実行すると以下のようになる。
ここまでで、AndroidとiOSのプロジェクト内には何らソースコードを書いていない。このようにすることで、AndroidとiOSで描画処理を共通化することができた。
参考サイト・記事
Xamarin.FormsとSkiaSharpを組み合わせたチュートリアル。英語だが、SkiaSharpを使う上で最小限のことがまとまっていてわかりやすい。
https://blog.xamarin.com/drawing-with-skiasharp/
自サイト内記事。AndroidでのViewの描画方法について。
https://zawapro.com/?p=331