在Xamarin Forms visual studio中为Grasient添加渐变背景

我是Xamarin Forms的新手,我为Menu创建了一个ContentPage。 我的背景需要线性渐变色。 但我找不到任何告诉我如何创建背景渐变颜色的链接。 我也希望在按钮背景的颜色位置像android中的选择器。 如果您有任何信息,请给予回复。

在下面的代码中,我们可以为下面的任何布局设置水平和垂直渐变(我把它放在#region中),如果你想编写另一个布局,只需在StackLayout上替换你的布局。

在PCL中:

using System; using Xamarin.Forms; namespace GradientColor { public class GradientColorStack : StackLayout { public Color StartColor { get; set; } public Color EndColor { get; set; } } } 

Xamarin.Android:

  using System; using GradientColor; using GradientColor.Droid; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; [assembly: ExportRenderer(typeof(GradientColorStack), typeof(GradientColorStackRenderer))] namespace GradientColor.Droid { public class GradientColorStackRenderer : VisualElementRenderer { private Color StartColor { get; set; } private Color EndColor { get; set; } protected override void DispatchDraw(global::Android.Graphics.Canvas canvas) { #region for Vertical Gradient //var gradient = new Android.Graphics.LinearGradient(0, 0, 0, Height, #endregion #region for Horizontal Gradient var gradient = new Android.Graphics.LinearGradient(0, 0, Width, 0, #endregion this.StartColor.ToAndroid(), this.EndColor.ToAndroid(), Android.Graphics.Shader.TileMode.Mirror); var paint = new Android.Graphics.Paint() { Dither = true, }; paint.SetShader(gradient); canvas.DrawPaint(paint); base.DispatchDraw(canvas); } protected override void OnElementChanged(ElementChangedEventArgs e) { base.OnElementChanged(e); if (e.OldElement != null || Element == null) { return; } try { var stack = e.NewElement as GradientColorStack; this.StartColor = stack.StartColor; this.EndColor = stack.EndColor; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(@"ERROR:", ex.Message); } } } } 

Xamarin.iOS:

  using System; using CoreAnimation; using CoreGraphics; using GradientColor; using GradientColor.iOS; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; [assembly: ExportRenderer(typeof(GradientColorStack), typeof(GradientColorStackRenderer))] namespace GradientColor.iOS { public class GradientColorStackRenderer : VisualElementRenderer { public override void Draw(CGRect rect) { base.Draw(rect); GradientColorStack stack = (GradientColorStack)this.Element; CGColor startColor = stack.StartColor.ToCGColor(); CGColor endColor = stack.EndColor.ToCGColor(); #region for Vertical Gradient var gradientLayer = new CAGradientLayer(); #endregion #region for Horizontal Gradient //var gradientLayer = new CAGradientLayer() //{ // StartPoint = new CGPoint(0, 0.5), // EndPoint = new CGPoint(1, 0.5) //}; #endregion gradientLayer.Frame = rect; gradientLayer.Colors = new CGColor[] { startColor, endColor }; NativeView.Layer.InsertSublayer(gradientLayer, 0); } } } 

在XAML中:

                       

使用此类将SkiaSharp Nuget添加到您的项目中。 无论您需要渐变,都可以在xaml中使用它。

 public partial class GradientView : ContentView { public Color StartColor { get; set; } = Color.Transparent; public Color EndColor { get; set; } = Color.Transparent; public bool Horizontal { get; set; } = false; public GradientView() { InitializeComponent(); SKCanvasView canvasView = new SKCanvasView(); canvasView.PaintSurface += OnCanvasViewPaintSurface; Content = canvasView; } void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) { SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); var colors = new SKColor[] { StartColor.ToSKColor(), EndColor.ToSKColor()}; SKPoint startPoint = new SKPoint(0,0); SKPoint endPoint = Horizontal ? new SKPoint(info.Width, 0) : new SKPoint(0, info.Height); var shader = SKShader.CreateLinearGradient(startPoint, endPoint, colors, null, SKShaderTileMode.Clamp); SKPaint paint = new SKPaint { Style = SKPaintStyle.Fill, Shader = shader }; canvas.DrawRect(new SKRect(0, 0, info.Width, info.Height), paint); } 

对于那些想要在Xamarin.Forms应用程序中使用全function渐变的人,我的代码是:

在你的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 } } 

在您的iOS项目中

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

在您的Android项目中

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 { 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 e) { base.OnElementChanged(e); if (e.OldElement != null || Element == null) return; try { if (e.NewElement is GradientLayoutRenderer layout) { Colors = layout.Colors; Mode = layout.Mode; } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(@"ERROR:", ex.Message); } } } } 

在UWP项目中

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

在您的XAML页面中

    

希望这会有所帮助!

目前还没有真正的绘图function。 您可能希望将图像设置为背景,可以为不同的文件夹(hdpi,mdpi,xhdpi等等)提供许多图片。或者您可以使用自定义渲染器将ContentPage类扩展为您自己的。

您可以在Xamarin论坛上查看此讨论。 https://forums.xamarin.com/discussion/22440/gradient-as-background-color

XFGloss项目增加了通过XAML添加渐变的function。

例如:

         ...  

要使用动态资源,您必须使您的属性可绑定,如下所示

  public static BindableProperty StartColorProperty = BindableProperty.Create(nameof(CustomContentPage), typeof(Color), typeof(CustomButton), default(Color), defaultBindingMode: BindingMode.OneWay); public Color StartColor { get { return (Color)GetValue(StartColorProperty); } set { SetValue(PaddingProperty, value); } } public static BindableProperty EndColorProperty = BindableProperty.Create(nameof(CustomContentPage), typeof(Color), typeof(CustomButton), default(Color), defaultBindingMode: BindingMode.OneWay); public Color EndColor { get { return (Color)GetValue(EndColorProperty); } set { SetValue(PaddingProperty, value); } }