今回は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);
}
}
}
これで出来上がりです!