枠線つきの円を描く必要にせまられたのでやってみました。
Frame を利用
Xamarin.Formsに円を描画する専用のコントロールはありませんが Frame を使えば描画可能です。
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyApp"
x:Class="MyApp.MyAppPage">
<Frame
BackgroundColor="Aqua"
OutlineColor="Navy"
WidthRequest="100"
HeightRequest="100"
CornerRadius="50"
Padding="0"
VerticalOptions="Center"
HorizontalOptions="Center">
</Frame>
</ContentPage>
こんな XAML にすると、
と、枠線のついた円が描けるのでこれでOKと思いきや Android だと、
枠線がつかねーじゃねーか!
実機でも同じ。
XAML でなく C# のコードでも試してみたものの枠線つかず。
プログラミングXamarinでは枠線付きの Frame が Android のキャプチャー画像付きで紹介されているんですが、どういうことなんでしょうかね...。
Frame をネストしてみる
仕方ないので Frame を Frame で囲んでみます。
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyApp"
x:Class="MyApp.MyAppPage">
<Frame
BackgroundColor="Navy"
WidthRequest="102"
HeightRequest="102"
CornerRadius="51"
Padding="1"
VerticalOptions="Center"
HorizontalOptions="Center">
<Frame
BackgroundColor="Aqua"
WidthRequest="100"
HeightRequest="100"
CornerRadius="50"
Padding="0"/>
</Frame>
</ContentPage>
これで、
いいですね。
いいですね。
じゃ、ついでに KitKat でも、
.....。
NControl を使ってみる
どうにも納得いかない結果になったので、別の手段をとってみます。
しかし、カスタムレンダラーは書きたくない。
ということで NControl というクロスプラットフォームな2D描画パッケージを使ってみます。
インストール
ソリューション内の各プロジェクト(PCL/iOS/Droid)に、下記のパッケージを追加します。
- NControl
- NControl.Controls
NControl.Controls は必須ではないはずですが、Xamarin.Formsの色をNControlの色に変換する拡張メソッドが追加されてなにかと便利なので入れておくと良いと思います。
初期化
iOS/Android に NControl の初期化コードを追加します。
iOS
using System;
using System.Collections.Generic;
using System.Linq;
using Foundation;
using UIKit;
using NControl.iOS; // <-- 追加
namespace MyApp.iOS
{
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
NControlViewRenderer.Init(); // <-- 追加
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
}
}
Android
using System;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using NControl.Droid; // <-- 追加
namespace MyApp.Droid
{
[Activity(Label = "MyApp.Droid", Icon = "@drawable/icon", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
NControlViewRenderer.Init(); // <-- 追加
LoadApplication(new App());
}
}
}
カスタムコントロールを作成
XAMLだけだと無理なんで、NControlView を継承したビューを作成します。
DrawingFunction というプロパティに描画用の関数を設定します。
FillEllipse というのが、1つめの引数で指定した領域を、2番目の色を使って楕円形を塗りつぶすメソッドです。
NControlView は Content プロパティを持っているので、これで NcontrolViewをネストして枠線と内側の円を描画します。
using System;
using Xamarin.Forms;
using NControl.Abstractions;
using NControl.Controls;
using NGraphics;
namespace MyApp
{
public class CircleView : NControlView
{
public CircleView()
{
Padding = 1;
DrawingFunction = (canvas, rect) => {
canvas.FillEllipse(rect, Xamarin.Forms.Color.Navy.ToNColor());
};
Content = new NControlView {
DrawingFunction = (canvas, rect) => {
canvas.FillEllipse(rect, Xamarin.Forms.Color.Aqua.ToNColor());
},
};
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyApp"
x:Class="MyApp.MyAppPage">
<local:CircleView
WidthRequest="100"
HeightRequest="100"
VerticalOptions="Center"
HorizontalOptions="Center"
/>
</ContentPage>
結果
うまくいったようです。
KitKat でも枠線が表示されていますね。
影がついていませんが、枠線つきの円を描画できました。
カスタムコントロールにバインド可能プロパティを追加すれば、XAMLから色指定とかいろいろできるかと。
NControl を使えば円だけでなく、多角形や曲線をつかったオブジェクトもカスタムレンダラーを使わずに実装できそうです。
とりあえずは以上です。