LoginSignup
3

More than 5 years have passed since last update.

Xamarin.Formsで枠線つきの円を描く

Last updated at Posted at 2017-09-08

枠線つきの円を描く必要にせまられたのでやってみました。

Frame を利用

Xamarin.Formsに円を描画する専用のコントロールはありませんが Frame を使えば描画可能です。

XAML
<?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 にすると、

ios_1.png

と、枠線のついた円が描けるのでこれでOKと思いきや Android だと、

a23_1.png

枠線がつかねーじゃねーか!

実機でも同じ。
XAML でなく C# のコードでも試してみたものの枠線つかず。

プログラミングXamarinでは枠線付きの Frame が Android のキャプチャー画像付きで紹介されているんですが、どういうことなんでしょうかね...。

Frame をネストしてみる

仕方ないので Frame を Frame で囲んでみます。

XAML
<?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>

これで、

ios_2.png

いいですね。

a23_2.png

いいですね。
じゃ、ついでに KitKat でも、

a19_2.png

.....。

NControl を使ってみる

どうにも納得いかない結果になったので、別の手段をとってみます。

しかし、カスタムレンダラーは書きたくない。

ということで NControl というクロスプラットフォームな2D描画パッケージを使ってみます。

インストール

ソリューション内の各プロジェクト(PCL/iOS/Droid)に、下記のパッケージを追加します。

  • NControl
  • NControl.Controls

NControl.Controls は必須ではないはずですが、Xamarin.Formsの色をNControlの色に変換する拡張メソッドが追加されてなにかと便利なので入れておくと良いと思います。

nuget.png

初期化

iOS/Android に NControl の初期化コードを追加します。

iOS

AppDelegate.cs
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

MainActivity.cs
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をネストして枠線と内側の円を描画します。

CircleView.cs
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());
                },
            };
        }
    }
}
XAML
<?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>

結果

ios_3.png

a23_3.png

a19_3.png

うまくいったようです。
KitKat でも枠線が表示されていますね。

影がついていませんが、枠線つきの円を描画できました。
カスタムコントロールにバインド可能プロパティを追加すれば、XAMLから色指定とかいろいろできるかと。

NControl を使えば円だけでなく、多角形や曲線をつかったオブジェクトもカスタムレンダラーを使わずに実装できそうです。

とりあえずは以上です。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3