Xamarin.Forms 点線(破線)のFrameの作り方

今回はXamarinのコントロール「Frame」の線を点線(破線)に変更したいと思います。

手順は下記の通りです。

1.共通プロジェクト内にコントロールを作成

using Xamarin.Forms;
namespace TestPrj {
    public class DashedFrame : Frame {
        // 線の太さ
        public static readonly BindableProperty DashedlineWeightProperty =
            BindableProperty.Create(
                nameof(DashedlineWeight),
                typeof(int),
                typeof(DashedFrame),
                1,
                propertyChanged:(bindable, oldValue, newValue) =>
                    ((DashedFrame)bindable)
                    .DashedlineWeight = (int)newValue
            );
        public int DashedlineWeight{
            get { return (int)GetValue(DashedlineWeightProperty); }
            set { SetValue(DashedlineWeightProperty, value); }
        }

        // 線の長さ
        public static readonly BindableProperty DashedlineWidthProperty =
            BindableProperty.Create(
                nameof(DashedlineWidth),
                typeof(int),
                typeof(DashedFrame),
                1,
                propertyChanged: (bindable, oldValue, newValue) =>
                     ((DashedFrame)bindable)
                     .DashedlineWidth = (int)newValue
             );
        public int DashedlineWidth
        {
            get { return (int)GetValue(DashedlineWidthProperty); }
            set { SetValue(DashedlineWidthProperty, value); }
        }

        // 線の間隔
        public static readonly BindableProperty DashedlineSpaceProperty =
            BindableProperty.Create(
                nameof(DashedlineSpace),
                typeof(int),
                typeof(DashedFrame),
                1,
                propertyChanged: (bindable, oldValue, newValue) =>
                     ((DashedFrame)bindable)
                     .DashedlineSpace = (int)newValue
             );
        public int DashedlineSpace
        {
            get { return (int)GetValue(DashedlineSpaceProperty); }
            set { SetValue(DashedlineSpaceProperty, value); }
        }
    }
}

2.Androidプロジェクト内に1で作成したコントロールのレンダラーを書く

using System;
using Android.Content;
using TestPrj;
using TestPrj.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(DashedFrame), typeof(DashedFrameRenderer))]
namespace TestPrj.Droid {
    public class DashedFrameRenderer : VisualElementRenderer<Frame> {
        public DashedFrameRenderer(Context context) : base(context) { }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Frame> e) {
            base.OnElementChanged(e);
            var dashedFrame = e.NewElement as DashedFrame;
            var gd = new Android.Graphics.Drawables.GradientDrawable();
            // BackgroundColorプロパティを反映
            gd.SetColor(dashedFrame.BackgroundColor.ToAndroid());
            // CornerRadiusプロパティを反映
            gd.SetCornerRadius(dashedFrame.CornerRadius);
            // DashedFrameの各プロパティをセット
            gd.SetStroke(
                dashedFrame.DashedlineWeight,
                dashedFrame.BorderColor.ToAndroid(),
                dashedFrame.DashedlineWidth,
                dashedFrame.DashedlineSpace
            );
            ViewGroup.SetBackground(gd);
        }
    }
}

3.iOSプロジェクト内に1で作成したコントロールのレンダラーを書く

using System;
using CoreAnimation;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using TestPrj;
using TestPrj.iOS;

[assembly: ExportRenderer(typeof(DashedFrame), typeof(DashedFrameRenderer))]
namespace TestPrj.iOS {
    public class DashedFrameRenderer : FrameRenderer {
        public DashedFrameRenderer(){}

        Color dashedColor;
        protected override void OnElementChanged(ElementChangedEventArgs<Frame> e) {
            base.OnElementChanged(e);
            if (e.NewElement != null) {
                dashedColor = Element.BorderColor;
                // FrameのBorderColorをクリアしておく
                Element.BorderColor = Color.Transparent;
            }
        }

        public override void LayoutSubviews() {
            base.LayoutSubviews();
            var dashedFrame = Element as DashedFrame;
            CAShapeLayer viewBorder = new CAShapeLayer();
            // CornerRadiusプロパティを反映
            viewBorder.CornerRadius = dashedFrame.CornerRadius;
            // BackgroundColorプロパティを反映
            viewBorder.FillColor = dashedFrame.BackgroundColor.ToCGColor();
            // BorderColorプロパティを反映
            viewBorder.StrokeColor = dashedColor.ToCGColor();
            // DashedFrameのDashedlineWeightプロパティをセット
            viewBorder.LineWidth = (nfloat)dashedFrame.DashedlineWeight;
            // DashedFrameのDashedlineWidth、DashedlineSpaceプロパティをセット
            viewBorder.LineDashPattern = new NSNumber[] {
                new NSNumber(dashedFrame.DashedlineWidth),
                new NSNumber(dashedFrame.DashedlineSpace)
            };
            viewBorder.Frame = NativeView.Bounds;
            viewBorder.Path = UIBezierPath.FromRect(NativeView.Bounds).CGPath;
            Layer.AddSublayer(viewBorder);
        }
    }
}

これで出来上がりです!

タイトルとURLをコピーしました