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);        }    }    } }


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

Popular posts from this blog

ScrollView in xamarin forms

Checkbox and RadioButon in xamarin forms

Navigation in Xamarin.Forms