Custom BoxView In xamarin forms
Step 1 :
Add the following class in PCL project :
public class ExtendedBoxView : BoxView
{ /// <summary> /// Respresents the background color of the button. /// </summary> public static readonly BindableProperty BorderRadiusProperty = BindableProperty.Create<ExtendedBoxView, double>(p => p.BorderRadius, 0);
public double BorderRadius { get { return (double)GetValue(BorderRadiusProperty); } set { SetValue(BorderRadiusProperty, value); } }
public static readonly BindableProperty StrokeProperty = BindableProperty.Create<ExtendedBoxView, Color>(p => p.Stroke, Color.Transparent);
public Color Stroke { get { return (Color)GetValue(StrokeProperty); } set { SetValue(StrokeProperty, value); } }
public static readonly BindableProperty StrokeThicknessProperty = BindableProperty.Create<ExtendedBoxView, double>(p => p.StrokeThickness, 0);
public double StrokeThickness { get { return (double)GetValue(StrokeThicknessProperty); } set { SetValue(StrokeThicknessProperty, value); } }
}
Step 2 : creating a renderer for each platform :
1- IOS :
[assembly: ExportRenderer(typeof(ExtendedBoxView), typeof(ExtendedBoxViewRenderer))] namespace Mobile.iOS.Renderers { public class ExtendedBoxViewRenderer : VisualElementRenderer<BoxView> { public ExtendedBoxViewRenderer() { }
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e) { base.OnElementChanged(e); if (Element == null) return;
Layer.MasksToBounds = true; Layer.CornerRadius = (float)((ExtendedBoxView)this.Element).BorderRadius / 2.0f; }
protected override void OnElementPropertyChanged(object sender,System.ComponentModel.PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); if (e.PropertyName == ExtendedBoxView.BorderRadiusProperty.PropertyName) { SetNeedsDisplay(); } }
public override void Draw(CGRect rect) { ExtendedBoxView roundedBoxView = (ExtendedBoxView)this.Element; using (var context = UIGraphics.GetCurrentContext()) { context.SetFillColor(roundedBoxView.Color.ToCGColor()); context.SetStrokeColor(roundedBoxView.Stroke.ToCGColor()); context.SetLineWidth((float)roundedBoxView.StrokeThickness);
var rCorner = this.Bounds.Inset((int)roundedBoxView.StrokeThickness / 2, (int)roundedBoxView.StrokeThickness / 2);
nfloat radius = (nfloat)roundedBoxView.BorderRadius; radius = (nfloat)Math.Max(0, Math.Min(radius, Math.Max(rCorner.Height / 2, rCorner.Width / 2)));
var path = CGPath.FromRoundedRect(rCorner, radius, radius); context.AddPath(path); context.DrawPath(CGPathDrawingMode.FillStroke); } } } }
Add the following class in PCL project :
public class ExtendedBoxView : BoxView
{ /// <summary> /// Respresents the background color of the button. /// </summary> public static readonly BindableProperty BorderRadiusProperty = BindableProperty.Create<ExtendedBoxView, double>(p => p.BorderRadius, 0);
public double BorderRadius { get { return (double)GetValue(BorderRadiusProperty); } set { SetValue(BorderRadiusProperty, value); } }
public static readonly BindableProperty StrokeProperty = BindableProperty.Create<ExtendedBoxView, Color>(p => p.Stroke, Color.Transparent);
public Color Stroke { get { return (Color)GetValue(StrokeProperty); } set { SetValue(StrokeProperty, value); } }
public static readonly BindableProperty StrokeThicknessProperty = BindableProperty.Create<ExtendedBoxView, double>(p => p.StrokeThickness, 0);
public double StrokeThickness { get { return (double)GetValue(StrokeThicknessProperty); } set { SetValue(StrokeThicknessProperty, value); } }
}
Step 2 : creating a renderer for each platform :
1- IOS :
[assembly: ExportRenderer(typeof(ExtendedBoxView), typeof(ExtendedBoxViewRenderer))] namespace Mobile.iOS.Renderers { public class ExtendedBoxViewRenderer : VisualElementRenderer<BoxView> { public ExtendedBoxViewRenderer() { }
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e) { base.OnElementChanged(e); if (Element == null) return;
Layer.MasksToBounds = true; Layer.CornerRadius = (float)((ExtendedBoxView)this.Element).BorderRadius / 2.0f; }
protected override void OnElementPropertyChanged(object sender,System.ComponentModel.PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); if (e.PropertyName == ExtendedBoxView.BorderRadiusProperty.PropertyName) { SetNeedsDisplay(); } }
public override void Draw(CGRect rect) { ExtendedBoxView roundedBoxView = (ExtendedBoxView)this.Element; using (var context = UIGraphics.GetCurrentContext()) { context.SetFillColor(roundedBoxView.Color.ToCGColor()); context.SetStrokeColor(roundedBoxView.Stroke.ToCGColor()); context.SetLineWidth((float)roundedBoxView.StrokeThickness);
var rCorner = this.Bounds.Inset((int)roundedBoxView.StrokeThickness / 2, (int)roundedBoxView.StrokeThickness / 2);
nfloat radius = (nfloat)roundedBoxView.BorderRadius; radius = (nfloat)Math.Max(0, Math.Min(radius, Math.Max(rCorner.Height / 2, rCorner.Width / 2)));
var path = CGPath.FromRoundedRect(rCorner, radius, radius); context.AddPath(path); context.DrawPath(CGPathDrawingMode.FillStroke); } } } }
2- Android :
[assembly: ExportRenderer(typeof(ExtendedBoxView), typeof(ExtendedBoxViewRenderer))] namespace Mobile.Droid { /// <summary> /// /// </summary> public class ExtendedBoxViewRenderer : VisualElementRenderer<BoxView> { /// <summary> /// /// </summary> public ExtendedBoxViewRenderer() { }
/// <summary> /// /// </summary> /// <param name="e"></param> protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e) { base.OnElementChanged(e);
SetWillNotDraw(false);
Invalidate(); }
/// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == ExtendedBoxView.BorderRadiusProperty.PropertyName) { Invalidate(); } }
/// <summary> /// /// </summary> /// <param name="canvas"></param> public override void Draw(Canvas canvas) { var box = Element as ExtendedBoxView; base.Draw(canvas); Paint myPaint = new Paint();
myPaint.SetStyle(Paint.Style.Stroke); myPaint.StrokeWidth = (float)box.StrokeThickness; myPaint.SetARGB(convertTo255ScaleColor(box.Color.A), convertTo255ScaleColor(box.Color.R), convertTo255ScaleColor(box.Color.G), convertTo255ScaleColor(box.Color.B)); myPaint.SetShadowLayer(20, 0, 5, Android.Graphics.Color.Argb(100, 0, 0, 0));
SetLayerType(Android.Views.LayerType.Software, myPaint);
var number = (float)box.StrokeThickness / 2; RectF rectF = new RectF( number, // left number, // top canvas.Width - number, // right canvas.Height - number // bottom );
var radius = (float)box.BorderRadius; canvas.DrawRoundRect(rectF, radius, radius, myPaint); }
/// <summary> /// /// </summary> /// <param name="color"></param> /// <returns></returns> private int convertTo255ScaleColor(double color) { return (int) Math.Ceiling(color * 255); }
}
}
Usage :
1- We first reference to our control with the namespace we defined earlier.
xmlns:Controls="clr-namespace:Mobile.Controls"
2- We then use the Control as follows and use properties defined at the beginning:
<Controls:ExtendedBoxView x:Name="search_boxview" Color="#444" BorderRadius="5" HorizontalOptions="CenterAndExpand" />
Comments
Post a Comment