对于那些想要在 Xamarin.Forms 应用程序中实现全功能渐变的人,有我的代码:
在您的 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<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);
}
}
}
在您的 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<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);
}
}
}
}
在 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<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);
}
}
}
}
在您的 XAML 页面中
<renderers:GradientLayout
ColorsList="#dd8f68,#a9a9a9,#3a3939"
Mode="ToBottomRight">
<!-- Your content -->
</renderers:GradientLayout>
希望这会有所帮助!