Gradient Color In Xamarin Forms(Gradient Button, StackLayout, Frame)

Gradient Color In Xamarin Forms(Gradient Button, Gradient StackLayout, Gradient Frame)

gradient color


Today, we are going to learn about , How to use Gradient Color In Xamarin Forms for Button, StackLayout and Frame, In Xamarin Forms we can't give Gradient Color directly, if we want to use Gradient Color to View or Controls then we need to customise controls or view.


What is Gradient Color?

Gradient Color Means , sometimes called a color ramp or color progression and in simple word we can say Gradient Color is Combination of two or more color.


Let's Start ,

Read About Custom Renderer

1. StackLayout Gradient Color :


Stacklayout is layout where you can arrange view and controls vertically and horizontally.

Now Question is How to give Gradient Color to StackLayout as Background Color?

First we need to create Custom Renderer because we cannot give gradient color directly to Stacklayout or view in Xamarin Forms.

Follow Below Steps:

Step 1 : Create StackLayout Custom Renderer class in PCL project :

 public class GradientStackLayout:StackLayout
 {

        //Peropeties 
        public Color StartColor
        {
            get; set;
        }

        public Color EndColor
        {
            get; set;
        }

        public GradientOrientation GradientColorOrientation
        {
            get; set;
        }
        // gradient orientation enum
        public enum GradientOrientation
        {
            Vertical,
            Horizontal
        }

    }


 here we create class with properties StartColor(for first color which you want to set), EndColor(for second color which you want to set) and GradientColorOrientation(for Gradient Orientation)

Setp 2:  Now, we need to write platform specific code for GradientStackLayout Class implementation 

Android : Create GradientStackLayoutRenderer and override DispatchDraw() method -(is what tells the children of the ViewGroup to be drawn)

[assembly: ExportRenderer(typeof(GradientStackLayout), typeof(GradientStackLayoutRenderer))]
namespace MyUIDemo.Droid.CustomRenderer
{
public class GradientStackLayoutRenderer:VisualElementRenderer<StackLayout>
    {
        public GradientStackLayoutRenderer(Context context):base(context)
        {

        }
        protected override void DispatchDraw(Canvas canvas)
        {
            base.DispatchDraw(canvas);
            LinearGradient gradient = null;

            // For Horizontal Gradient
            if(((GradientStackLayout)Element).GradientColorOrientation==GradientStackLayout.GradientOrientation.Horizontal)
            {
                 gradient = new Android.Graphics.LinearGradient(0, 0, Width, 0,



                      ((GradientStackLayout)Element).StartColor.ToAndroid(),
                      ((GradientStackLayout)Element).EndColor.ToAndroid(),

                      Android.Graphics.Shader.TileMode.Mirror);

            }
            //For Vertical Gradient
            if (((GradientStackLayout)Element).GradientColorOrientation == GradientStackLayout.GradientOrientation.Vertical)
            {
                gradient = new Android.Graphics.LinearGradient(0, 0, 0, Height,



                     ((GradientStackLayout)Element).StartColor.ToAndroid(),
                     ((GradientStackLayout)Element).EndColor.ToAndroid(),

                     Android.Graphics.Shader.TileMode.Mirror);

            }

            var paint = new Android.Graphics.Paint()
            {
                Dither = true,
            };
            paint.SetShader(gradient);
            canvas.DrawPaint(paint);
            base.DispatchDraw(canvas);
        }
    }

}


For iOS:Create GradientStackLayoutRenderer and override Draw() method -(Draw shape)


[assembly: ExportRenderer(typeof(GradientStackLayout), typeof(GradientStackLayoutRenderer))]
namespace MyUIDemo.iOS.CustomRenderer
{

 public class GradientStackLayoutRenderer:VisualElementRenderer<StackLayout> {
        public override void Draw(CGRect rect)
        {
            base.Draw(rect);
            if (this.Element != null)
            {
                if (this.Element is GradientStackLayout)
                {

                    var obj = (GradientStackLayout)this.Element;
                    CGColor StartColor = obj.StartColor.ToCGColor();
                    CGColor EndColor = obj.EndColor.ToCGColor();
                    var gradientLayer = new CAGradientLayer();
                    gradientLayer.Frame = rect;
                    gradientLayer.Colors = new CGColor[] { StartColor, EndColor };

                  //for horizontal gradient                     if (obj.GradientColorOrientation == GradientStackLayout.GradientOrientation.Horizontal)
                    {
                        gradientLayer.StartPoint = new CGPoint(0.0, 0.5);
                        gradientLayer.EndPoint = new CGPoint(1.0, 0.5);
                    }
                    NativeView.Layer.InsertSublayer(gradientLayer, 0);
                }
            }
        }
    }

}


2. Frame Gradient Color:


We can customise Frame same as StackLayout:

Step 1: Create GradientFrame class in PCL :

 public class GradientFrame:Frame
    {
        public enum GradientOrientation
        {
            Vertical,
            Horizontal
        }

        public Color StartColor
        {
            get; set;
        }

        public Color EndColor
        {
            get; set;
        }
        public GradientOrientation GradientColorOrientation
        {
            get; set;
        }

    }



Step 2 : Create GradientFrameRenderer class in iOS and Android project:

Android:

[assembly: ExportRenderer(typeof(GradientFrame), typeof(GradientFrameRenderer))]
namespace MyUIDemo.Droid.CustomRenderer
{

    public class GradientFrameRenderer : VisualElementRenderer<Frame>
    {
        public GradientFrameRenderer(Context context) : base(context)
        {

        }
        protected override void DispatchDraw(Canvas canvas)
        {
            base.DispatchDraw(canvas);
            LinearGradient gradient = null;

            //for horizontal gradient
            if (((GradientFrame)Element).GradientColorOrientation == GradientFrame.GradientOrientation.Horizontal)
            {
                gradient = new Android.Graphics.LinearGradient(0, 0, Width, 0,



                     ((GradientFrame)Element).StartColor.ToAndroid(),
                     ((GradientFrame)Element).EndColor.ToAndroid(),

                     Android.Graphics.Shader.TileMode.Mirror);

            }
            //for vertical gradient
            if (((GradientFrame)Element).GradientColorOrientation == GradientFrame.GradientOrientation.Vertical)
            {
                gradient = new Android.Graphics.LinearGradient(0, 0, 0, Height,



                     ((GradientFrame)Element).StartColor.ToAndroid(),
                     ((GradientFrame)Element).EndColor.ToAndroid(),

                     Android.Graphics.Shader.TileMode.Mirror);

            }

            var paint = new Android.Graphics.Paint()
            {
                Dither = true,
            };
            paint.SetShader(gradient);
            canvas.DrawPaint(paint);
            base.DispatchDraw(canvas);
        }
    }
}

iOS:

[assembly: ExportRenderer(typeof(GradientFrame), typeof(GradientFrameRenderer))]
namespace MyUIDemo.iOS.CustomRenderer
{

 public class GradientFrameRenderer :VisualElementRenderer<Frame>{
        public override void Draw(CGRect rect)
        {
            base.Draw(rect);
            if (this.Element != null)
            {
                if (this.Element is GradientFrame)
                {

                    var obj = (GradientFrame)this.Element;
                    CGColor StartColor = obj.StartColor.ToCGColor();
                    CGColor EndColor = obj.EndColor.ToCGColor();
                    var gradientLayer = new CAGradientLayer();
                    gradientLayer.Frame = rect;
                    gradientLayer.Colors = new CGColor[] { StartColor, EndColor };

//for horizontal gra                     if (obj.GradientColorOrientation == GradientFrame.GradientOrientation.Horizontal)
                    {
                        gradientLayer.StartPoint = new CGPoint(0.0, 0.5);
                        gradientLayer.EndPoint = new CGPoint(1.0, 0.5);
                    }
                    NativeView.Layer.InsertSublayer(gradientLayer, 0);
                }
            }
        }
    }

}


3. Button Gradient Color :

We can customise Button Color like above :

Step 1: Create ButtonGradient Class in PCL :

  public class GradientButton : Button
     {

        public enum GradientOrientation { 
        Vertical,
        Horizontal
        }
        //properties
        public Color StartColor
        {
            get;set;
        }

        public Color EndColor
        {
            get;set;
        }
        
        public GradientOrientation GradientColorOrientation
        {
            get;set;
        }
       
    }


Step 2 : Create GradientButtonRenderer in Android and iOS :

Android:

[assembly:ExportRenderer(typeof(GradientButton),typeof(GradientButtonRenderer))]
namespace MyUIDemo.Droid.CustomRenderer
{
    public class GradientButtonRenderer:ButtonRenderer
    {
        public GradientButtonRenderer(Context context):base(context)
        {
        }

        protected override void DispatchDraw(Canvas canvas)
        {

            LinearGradient gradient = null;

            // For Horizontal Gradient
            if (((GradientButton)Element).GradientColorOrientation == GradientButton.GradientOrientation.Horizontal)
            {
                gradient = new Android.Graphics.LinearGradient(0, 0, Width, 0,



                     ((GradientButton)Element).StartColor.ToAndroid(),
                     ((GradientButton)Element).EndColor.ToAndroid(),

                     Android.Graphics.Shader.TileMode.Mirror);

            }
            //For Veritical Gradient
            if (((GradientButton)Element).GradientColorOrientation == GradientButton.GradientOrientation.Vertical)
            {
                gradient = new Android.Graphics.LinearGradient(0, 0, 0, Height,



                     ((GradientButton)Element).StartColor.ToAndroid(),
                     ((GradientButton)Element).EndColor.ToAndroid(),

                     Android.Graphics.Shader.TileMode.Mirror);

            }

            var paint = new Android.Graphics.Paint()
            {
                Dither = true,
            };
            paint.SetShader(gradient);
            canvas.DrawPaint(paint);
            base.DispatchDraw(canvas);
        }

    }

}

iOS:
[assembly: ExportRenderer(typeof(GradientButton), typeof(GradientButtonRenderer))]
namespace MyUIDemo.iOS.CustomRenderer
{
    public class GradientButtonRenderer : ButtonRenderer
    {

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

        }
        public override void Draw(CGRect rect)
        {
            base.Draw(rect);
            if (this.Element != null)
            {
                if (this.Element is GradientButton)
                {

                    var obj = (GradientButton)this.Element;
                    CGColor StartColor = obj.StartColor.ToCGColor();
                    CGColor EndColor = obj.EndColor.ToCGColor();
                    var gradientLayer = new CAGradientLayer();
                    gradientLayer.Frame = rect;
                    gradientLayer.Colors = new CGColor[] { StartColor, EndColor};

                    //for horizontal orientation
                    if (obj.GradientColorOrientation == GradientButton.GradientOrientation.Horizontal)
                    {
                        gradientLayer.StartPoint = new CGPoint(0.0, 0.5);
                        gradientLayer.EndPoint = new CGPoint(1.0, 0.5);
                    }
                    NativeView.Layer.InsertSublayer(gradientLayer,0);
                }
            }
        }
    }

}


Let's Use Above View in 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:MyUIDemo"
    xmlns:Renderer="clr-namespace:MyUIDemo.CustomRenderer"
    x:Class="MyUIDemo.MainPage">
    <StackLayout
        VerticalOptions="CenterAndExpand"
        HorizontalOptions="FillAndExpand"
        Padding="20">
        <Renderer:GradientStackLayout
            Padding="10"
            StartColor="#d1bf56"
            EndColor="#b0d10d"
            HeightRequest="200">
            <Label
                Text="Gradient StackLayout"
                TextColor="Black"
                VerticalOptions="CenterAndExpand"
                VerticalTextAlignment="Center"
                HorizontalTextAlignment="Center" />
        </Renderer:GradientStackLayout>
        <Renderer:GradientFrame
            Padding="10"
            StartColor="#1dbfac"
            EndColor="#19bd73"
            HeightRequest="200">
            <Label
                Text="Gradient Frame"
                TextColor="Black"
                VerticalTextAlignment="Center"
                HorizontalTextAlignment="Center" />
        </Renderer:GradientFrame>
        <Renderer:GradientButton
            Text="Button"
            GradientColorOrientation="Horizontal"
            TextColor="White"
            BackgroundColor="Transparent"
            StartColor="#0517a1"
            EndColor="#731282" />
    </StackLayout>
</ContentPage>


Following Properties you can set for XAML:

1. StartColor - to set first color
2. EndColor - to set second color
3. GradientColorOrientation - to set Gradient Color Orientation (Vertical and Horizontal)


ScreenShot :
Android:

iOS: 
ios gradient xamarin forms





Gradient Color In Xamarin Forms(Gradient Button, StackLayout, Frame) Gradient Color In Xamarin Forms(Gradient Button, StackLayout, Frame) Reviewed by Dev Tech Solution on September 29, 2019 Rating: 5

10 comments:

  1. Woah!! Such a piece of the nice information you have shared here, I have read the entire post and I must say that the information is very helpful for me.


    Xamarin Development services in Indore

    ReplyDelete
  2. Thanks for this - on android in the button renderer the background to the containing view is set but the button is not touched. I copied the code exactly. Any ideas why?

    https://gyazo.com/153b73bcced7be7a71013a98dd7e5df5

    ReplyDelete
    Replies
    1. @adamisrel, can you share your code ?

      Delete
    2. I've used the exact same code as you (copy paste it) and also get the strange behaviour on my buttons...

      Delete
    3. I've same bug like @adamisreal ... any advice?

      Delete
  3. Is it possible to get rounded corners?

    ReplyDelete
  4. Replies
    1. @d-Nguyen, You can add radius to canvas in Custom Renderer, like below,
      For android:
      var path = new Path();
      var radius = 40;
      path.AddRoundRect(new RectF(0, 0, Width, Height),
      new float[] { radius, radius, radius, radius, radius, radius, radius, radius },
      Path.Direction.Ccw);

      canvas.Save();
      canvas.ClipPath(path);
      ............Put above code before canvas.DrawPaint(paint); method ...........
      For iOS:
      add corner radius to GradientLayer
      gradientLayer.CornerRadius = 20;

      Hope, it will help you..

      Delete
  5. How to create Gradient Color in Xamarin Forms for UWP project

    ReplyDelete
  6. Nice blog! I really loved reading through this Blog... Thanks for sharing such a very interesting post with us and keep blogging. Visit our website-
    Xamarin App Developers
    web and App Development company
    ABP .io Development company

    ReplyDelete

Powered by Blogger.