For those who want a full-featured gradient in Xamarin.Forms applications, there is my code:
In your pcl
GradientLayout.cs
using Xamarin.Forms; namespace MyProject.Renderers { public class GradientLayout : StackLayout { public string ColorsList { get; set; } public Color[] Colors { get { string[] hex = ColorsList.Split(','); Color[] colors = new Color[hex.Length]; for (int i = 0; i < hex.Length; i++) { colors[i] = Color.FromHex(hex[i].Trim()); } return colors; } } public GradientColorStackMode Mode { get; set; } } }
GradientColorStackMode.cs
namespace MyProject.Renderers { public enum GradientColorStackMode { ToRight, ToLeft, ToTop, ToBottom, ToTopLeft, ToTopRight, ToBottomLeft, ToBottomRight } }
In your iOS project
GradientLayoutRenderer.cs
using CoreAnimation; using CoreGraphics; using MyProject.Renderers; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; [assembly: ExportRenderer(typeof(GradientLayout), typeof(GradientLayoutRenderer))] namespace MyProject.iOS.Renderers { public class GradientLayoutRenderer : VisualElementRenderer<StackLayout> { public override void Draw(CGRect rect) { base.Draw(rect); GradientLayout layout = (GradientLayout)Element; CGColor[] colors = new CGColor[layout.Colors.Length]; for (int i = 0, l = colors.Length; i < l; i++) { colors[i] = layout.Colors[i].ToCGColor(); } var gradientLayer = new CAGradientLayer(); switch (layout.Mode) { default: case GradientColorStackMode.ToRight: gradientLayer.StartPoint = new CGPoint(0, 0.5); gradientLayer.EndPoint = new CGPoint(1, 0.5); break; case GradientColorStackMode.ToLeft: gradientLayer.StartPoint = new CGPoint(1, 0.5); gradientLayer.EndPoint = new CGPoint(0, 0.5); break; case GradientColorStackMode.ToTop: gradientLayer.StartPoint = new CGPoint(0.5, 0); gradientLayer.EndPoint = new CGPoint(0.5, 1); break; case GradientColorStackMode.ToBottom: gradientLayer.StartPoint = new CGPoint(0.5, 1); gradientLayer.EndPoint = new CGPoint(0.5, 0); break; case GradientColorStackMode.ToTopLeft: gradientLayer.StartPoint = new CGPoint(1, 0); gradientLayer.EndPoint = new CGPoint(0, 1); break; case GradientColorStackMode.ToTopRight: gradientLayer.StartPoint = new CGPoint(0, 1); gradientLayer.EndPoint = new CGPoint(1, 0); break; case GradientColorStackMode.ToBottomLeft: gradientLayer.StartPoint = new CGPoint(1, 1); gradientLayer.EndPoint = new CGPoint(0, 0); break; case GradientColorStackMode.ToBottomRight: gradientLayer.StartPoint = new CGPoint(0, 0); gradientLayer.EndPoint = new CGPoint(1, 1); break; } gradientLayer.Frame = rect; gradientLayer.Colors = colors; NativeView.Layer.InsertSublayer(gradientLayer, 0); } } }
In your Android project
GradientLayoutRenderer.cs
using System; using Android.Content; using MyProject.Renderers; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; [assembly: ExportRenderer(typeof(GradientLayout), typeof(GradientLayoutRenderer))] namespace MyProject.Droid.Renderers { public class GradientLayoutRenderer : VisualElementRenderer<StackLayout> { private Color[] Colors { get; set; } private GradientColorStackMode Mode { get; set; } public GradientLayoutRenderer(Context ctx) : base(ctx) { } protected override void DispatchDraw(global::Android.Graphics.Canvas canvas) { Android.Graphics.LinearGradient gradient; int[] colors = new int[Colors.Length]; for (int i = 0, l = Colors.Length; i < l; i++) { colors[i] = Colors[i].ToAndroid().ToArgb(); } switch (Mode) { default: case GradientColorStackMode.ToRight: gradient = new Android.Graphics.LinearGradient(0, 0, Width, 0, colors, null, Android.Graphics.Shader.TileMode.Mirror); break; case GradientColorStackMode.ToLeft: gradient = new Android.Graphics.LinearGradient(Width, 0, 0, 0, colors, null, Android.Graphics.Shader.TileMode.Mirror); break; case GradientColorStackMode.ToTop: gradient = new Android.Graphics.LinearGradient(0, Height, 0, 0, colors, null, Android.Graphics.Shader.TileMode.Mirror); break; case GradientColorStackMode.ToBottom: gradient = new Android.Graphics.LinearGradient(0, 0, 0, Height, colors, null, Android.Graphics.Shader.TileMode.Mirror); break; case GradientColorStackMode.ToTopLeft: gradient = new Android.Graphics.LinearGradient(Width, Height, 0, 0, colors, null, Android.Graphics.Shader.TileMode.Mirror); break; case GradientColorStackMode.ToTopRight: gradient = new Android.Graphics.LinearGradient(0, Height, Width, 0, colors, null, Android.Graphics.Shader.TileMode.Mirror); break; case GradientColorStackMode.ToBottomLeft: gradient = new Android.Graphics.LinearGradient(Width, 0, 0, Height, colors, null, Android.Graphics.Shader.TileMode.Mirror); break; case GradientColorStackMode.ToBottomRight: gradient = new Android.Graphics.LinearGradient(0, 0, Width, Height, colors, null, Android.Graphics.Shader.TileMode.Mirror); break; } var paint = new Android.Graphics.Paint() { Dither = true, }; paint.SetShader(gradient); canvas.DrawPaint(paint); base.DispatchDraw(canvas); } protected override void OnElementChanged(ElementChangedEventArgs<StackLayout> e) { base.OnElementChanged(e); if (e.OldElement != null || Element == null) return; try { if (e.NewElement is GradientLayout layout) { Colors = layout.Colors; Mode = layout.Mode; } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(@"ERROR:", ex.Message); } } } }
In the UWP project
GradientLayoutRenderer.cs
using System; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media; using MyProject.Renderers; using Xamarin.Forms; using Xamarin.Forms.Platform.UWP; using Point = Windows.Foundation.Point; [assembly: ExportRenderer(typeof(GradientLayout), typeof(GradientLayoutRenderer))] namespace MyProject.UWP.Renderers { public class GradientLayoutRenderer : VisualElementRenderer<StackLayout, Panel> { private Color[] Colors { get; set; } private GradientColorStackMode Mode { get; set; } protected override void UpdateBackgroundColor() { base.UpdateBackgroundColor(); LinearGradientBrush gradient; GradientStopCollection stopCollection = new GradientStopCollection(); for (int i = 0, l = Colors.Length; i < l; i++) { stopCollection.Add(new GradientStop { Color = Windows.UI.Color.FromArgb((byte)(Colors[i].A * byte.MaxValue), (byte)(Colors[i].R * byte.MaxValue), (byte)(Colors[i].G * byte.MaxValue), (byte)(Colors[i].B * byte.MaxValue)), Offset = (double)i / Colors.Length }); } switch (Mode) { default: case GradientColorStackMode.ToRight: gradient = new LinearGradientBrush { GradientStops = stopCollection, StartPoint = new Point(0, 0.5), EndPoint = new Point(1, 0.5) }; break; case GradientColorStackMode.ToLeft: gradient = new LinearGradientBrush { GradientStops = stopCollection, StartPoint = new Point(1, 0.5), EndPoint = new Point(0, 0.5) }; break; case GradientColorStackMode.ToTop: gradient = new LinearGradientBrush { GradientStops = stopCollection, StartPoint = new Point(0.5, 1), EndPoint = new Point(0.5, 0) }; break; case GradientColorStackMode.ToBottom: gradient = new LinearGradientBrush { GradientStops = stopCollection, StartPoint = new Point(0.5, 0), EndPoint = new Point(0.5, 1) }; break; case GradientColorStackMode.ToTopLeft: gradient = new LinearGradientBrush { GradientStops = stopCollection, StartPoint = new Point(1, 1), EndPoint = new Point(0, 0) }; break; case GradientColorStackMode.ToTopRight: gradient = new LinearGradientBrush { GradientStops = stopCollection, StartPoint = new Point(0, 1), EndPoint = new Point(1, 0) }; break; case GradientColorStackMode.ToBottomLeft: gradient = new LinearGradientBrush { GradientStops = stopCollection, StartPoint = new Point(1, 0), EndPoint = new Point(0, 1) }; break; case GradientColorStackMode.ToBottomRight: gradient = new LinearGradientBrush { GradientStops = stopCollection, StartPoint = new Point(0, 0), EndPoint = new Point(1, 1) }; break; } Background = gradient; } protected override void OnElementChanged(ElementChangedEventArgs<StackLayout> e) { base.OnElementChanged(e); if (e.OldElement != null || Element == null) return; try { if (e.NewElement is GradientLayout stack) { Colors = stack.Colors; Mode = stack.Mode; UpdateBackgroundColor(); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(@"ERROR:", ex.Message); } } } }
On your XAML pages
<renderers:GradientLayout ColorsList="#dd8f68,#a9a9a9,#3a3939" Mode="ToBottomRight"> </renderers:GradientLayout>
Hope this helps!