Gradient Color In Xamarin Forms(Gradient Button, Gradient StackLayout, Gradient Frame)
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
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)
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);
}
}
}
}
}
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>
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:
Gradient Color In Xamarin Forms(Gradient Button, StackLayout, Frame)
Reviewed by Dev Tech Solution
on
September 29, 2019
Rating:
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.
ReplyDeleteXamarin Development services in Indore
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?
ReplyDeletehttps://gyazo.com/153b73bcced7be7a71013a98dd7e5df5
@adamisrel, can you share your code ?
DeleteI've used the exact same code as you (copy paste it) and also get the strange behaviour on my buttons...
DeleteI've same bug like @adamisreal ... any advice?
DeleteIs it possible to get rounded corners?
ReplyDeletelike corner radius?
ReplyDelete@d-Nguyen, You can add radius to canvas in Custom Renderer, like below,
DeleteFor 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..
How to create Gradient Color in Xamarin Forms for UWP project
ReplyDeleteNice blog! I really loved reading through this Blog... Thanks for sharing such a very interesting post with us and keep blogging. Visit our website-
ReplyDeleteXamarin App Developers
web and App Development company
ABP .io Development company