向 Xamarin Forms Visual Studio 中的布局添加渐变背景
Posted
技术标签:
【中文标题】向 Xamarin Forms Visual Studio 中的布局添加渐变背景【英文标题】:Add Gradient background to layouts in Xamarin Forms visual studio 【发布时间】:2015-05-05 02:13:07 【问题描述】:我是 Xamarin Forms 的新手,我为 Menu 创建了一个 ContentPage。我需要在其背景上使用线性渐变颜色。但我找不到任何告诉我如何创建背景渐变颜色的链接。我也想要按钮背景的颜色位置,比如 android 中的选择器。如果您有任何信息,请回复。
【问题讨论】:
你找到任何解决方案或插件了吗? 没有仍在搜索,一种方法是使用图像。但不方便。其他无法集成的 C# 库。 另见forums.xamarin.com/discussion/22440/… 【参考方案1】:在下面的代码中,我们可以为下面我为 StackLayout 编写的任何布局设置水平和垂直渐变(我把它放在#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<StackLayout>
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<StackLayout> 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<StackLayout>
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 中:
<?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:GradientColor; assembly:GradientColor" x:Class="GradientColor.GradientColorPage">
<Grid VerticalOptions="FillAndExpand" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" BackgroundColor="Olive">
<StackLayout VerticalOptions="Center">
<Label Text="Normal color for stacklayout" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="White"/>
</StackLayout>
</Grid>
<Grid Grid.Row="1">
<local:GradientColorStack StartColor="Green" EndColor="Red">
<StackLayout VerticalOptions="CenterAndExpand">
<Label Text="Gradient color for StackLayout" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="White"/>
</StackLayout>
</local:GradientColorStack>
</Grid>
</Grid>
</ContentPage>
【讨论】:
Venkata Swamy Balaraju 原样,它工作得很好,但是说VisualElementRenderer
的调用已经过时了,我担心它现在可能工作,但将来会中断,你知道吗如何使代码保持最新?
@Lvkz 我遇到了同样的问题(我喜欢将警告视为错误,因此必须解决所有过时的警告)。我在类中添加了一个非默认构造函数,所以在我的例子中:protected GradientAbsoluteLayoutRenderer(Context context) : base(context)
解决了警告。如果我能说服我的 'droid 模拟器真正启动,我会测试它并让你知道它是否正常工作..
^^ 应该是一个公共构造函数。工作。
抱歉复活一个旧线程...首先,谢谢!它为我节省了很多时间。可以为其他人节省大量时间的方法是将 Android 的 DrawPaint
更改为 DrawRect
调用。在较新的 Android 构建的某些情况下,这种行为莫名其妙。不确定是 XF 还是 Android 应该受到责备,但这对我来说是解决办法。 HTH。
将Android上的DrawPaint改为canvas.DrawRect(new Android.Graphics.Rect(0, 0, Width, Height), paint);以防止它在整个屏幕上绘制。【参考方案2】:
对于那些想要在 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>
希望这会有所帮助!
【讨论】:
感谢这个实现拯救了我的培根。我能找到的唯一一篇处理 Android、IO 和 UWP 的帖子 有人可以帮我完成这个实现吗?在 PCL 中,Colors 数组永远不会创建/初始化。因为它是空的,所以我得到了一个例外。我只是好奇如何/在哪里定义数组中的颜色。在 xaml 中定义了 ColorsList,但这就是我所能看到的。 :P @Valerie 您是否在 xaml 文档中定义了 GradientLayout 的 ColorsList 属性?由于 Colors 数组只是一个 getter,因此您无法直接编辑此数组,因为它是使用 ColorsList 中的值自动生成的 @na2axl 感谢您的支持。是的,我复制了具有 ColorsList 参数的示例 xaml。当我使用 Freshmvvm 时,可能是 UI 加载的时间问题。 @Valerie 抱歉,但我不知道 Freshmvvm 的行为,所以我不能说这是问题的根源。但是您可以尝试在 GradientLayout 类中为 ColorsList 使用默认值,因此如果这是一个绑定问题,则将使用默认值来代替....【参考方案3】:将 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);
【讨论】:
你能发布一下 xaml 的样子吗? 将本地命名空间添加到 xaml,然后像这样使用 GradientView:目前还没有真正的绘图功能可以做到这一点。您可能想要将图像设置为背景,您可以为不同的文件夹(hdpi、mdpi、xhdpi 等)提供许多图片 或者您可以使用custom renderers 将 ContentPage 类扩展为您自己的。
您可以在 Xamarin 论坛上查看此讨论。 https://forums.xamarin.com/discussion/22440/gradient-as-background-color
【讨论】:
【参考方案5】:有史以来第一次对 SO 发表评论。
使用na2xl 回答作为效果
Effects 可以附加到不同的组件,完全可重用,并且不会强迫您对 Forms 组件进行子类化。
我添加了一个定位系统来调整每种颜色在渐变中的开始和结束位置 - 0 绝对开始/1 绝对结束。
在 NetStandard 库中
using System.Linq;
using Xamarin.Forms;
namespace YourProject.Effects
public class GradientEffect : RoutingEffect
public GradientEffect() : base("YourCompany.GradientEffect")
public string Colors get; set;
public GradientMode Mode get; set;
public Color[] ColorList => Colors.Split(',').Select(i => Color.FromHex(i.Trim())).ToArray();
public string Locations get; set;
public float[] LocationList => Locations.Split(',').Select(float.Parse).ToArray();
public enum GradientMode
ToRight,
ToLeft,
ToTop,
ToBottom,
ToTopLeft,
ToTopRight,
ToBottomLeft,
ToBottomRight,
Null
在 iOS 项目中
using System;
using System.Linq;
using CoreAnimation;
using CoreGraphics;
using Foundation;
using YourProject.Effects;
using YourProject.iOS.Effects;
using Serilog;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly:ResolutionGroupName ("YourCompany")]
[assembly: ExportEffect(typeof(IosGradientEffect), "GradientEffect")]
namespace YourProject.iOS.Effects
public class IosGradientEffect : PlatformEffect
protected override void OnAttached()
try
var nativeView = Control ?? Container;
var effect = (GradientEffect) Element.Effects.FirstOrDefault(e => e is GradientEffect);
if (effect == null) return;
var colors = effect.ColorList.Select(i => i.ToCGColor()).ToArray();
var gradientLayer = new CAGradientLayer
Locations = effect.LocationList?.Select(i => new NSNumber(i)).ToArray()
;
switch (effect.Mode)
default:
gradientLayer.StartPoint = new CGPoint(0, 0.5);
gradientLayer.EndPoint = new CGPoint(1, 0.5);
break;
case GradientMode.ToLeft:
gradientLayer.StartPoint = new CGPoint(1, 0.5);
gradientLayer.EndPoint = new CGPoint(0, 0.5);
break;
case GradientMode.ToTop:
gradientLayer.StartPoint = new CGPoint(0.5, 1);
gradientLayer.EndPoint = new CGPoint(0.5, 0);
break;
case GradientMode.ToBottom:
gradientLayer.StartPoint = new CGPoint(0.5, 0);
gradientLayer.EndPoint = new CGPoint(0.5, 1);
break;
case GradientMode.ToTopLeft:
gradientLayer.StartPoint = new CGPoint(1, 1);
gradientLayer.EndPoint = new CGPoint(0, 0);
break;
case GradientMode.ToTopRight:
gradientLayer.StartPoint = new CGPoint(0, 1);
gradientLayer.EndPoint = new CGPoint(1, 0);
break;
case GradientMode.ToBottomLeft:
gradientLayer.StartPoint = new CGPoint(1, 0);
gradientLayer.EndPoint = new CGPoint(0, 1);
break;
case GradientMode.ToBottomRight:
gradientLayer.StartPoint = new CGPoint(0, 0);
gradientLayer.EndPoint = new CGPoint(1, 1);
break;
gradientLayer.Frame = nativeView.Bounds;
gradientLayer.Colors = colors;
nativeView.Layer.InsertSublayer(gradientLayer, 0);
catch (Exception ex)
Log.Fatal(ex.Message);
protected override void OnDetached()
Log.Debug("Gradient Effect Detached");
**在Android项目中**
using System;
using System.Linq;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Graphics.Drawables.Shapes;
using YourProject.Droid.Effects;
using YourProject.Effects;
using Serilog;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly:ResolutionGroupName ("YourCompany")]
[assembly: ExportEffect(typeof(AndroidGradientEffect), "GradientEffect")]
namespace YourProject.Droid.Effects
public class AndroidGradientEffect : PlatformEffect
protected override void OnAttached()
try
var effect = (GradientEffect) Element.Effects.FirstOrDefault(e => e is GradientEffect);
var nativeView = Control ?? Container;
var colors = effect.ColorList.Select(i => i.ToAndroid().ToArgb()).ToArray();
var paint = new PaintDrawable();
paint.Shape = new RectShape();
paint.SetShaderFactory(new GradientShaderFactory(colors, effect.LocationList, Shader.TileMode.Mirror, effect.Mode));
nativeView.SetBackgroundDrawable(paint);
catch (Exception ex)
Log.Fatal("Couldn't set property for view with effect ex:" + ex.Message);
protected override void OnDetached()
Log.Debug("Android Gradient Effect detached");
internal class GradientShaderFactory : ShapeDrawable.ShaderFactory
private readonly Shader.TileMode _tileMode;
private readonly int[] _colors;
private readonly float[] _locations;
private readonly GradientMode _gradientMode;
internal GradientShaderFactory(int[] colors, float[] locations, Shader.TileMode tileMode,
GradientMode gradientMode)
_colors = colors;
_locations = locations;
_tileMode = tileMode;
_gradientMode = gradientMode;
public override Shader Resize(int width, int height)
LinearGradient gradient;
switch (_gradientMode)
default:
gradient = new LinearGradient(0, 0, width, 0, _colors, _locations,
_tileMode);
break;
case GradientMode.ToLeft:
gradient = new LinearGradient(width, 0, 0, 0, _colors, _locations,
_tileMode);
break;
case GradientMode.ToTop:
gradient = new LinearGradient(0, height, 0, 0, _colors, _locations,
_tileMode);
break;
case GradientMode.ToBottom:
gradient = new LinearGradient(0, 0, 0, height, _colors, _locations,
_tileMode);
break;
case GradientMode.ToTopLeft:
gradient = new LinearGradient(width, height, 0, 0,
_colors, _locations,
_tileMode);
break;
case GradientMode.ToTopRight:
gradient = new LinearGradient(0, height, width,0 ,
_colors, _locations,
_tileMode);
break;
case GradientMode.ToBottomLeft:
gradient = new LinearGradient(width, 0, 0, height,
_colors, _locations,
_tileMode);
break;
case GradientMode.ToBottomRight:
gradient = new LinearGradient(0, 0, width, height,
_colors,_locations,
_tileMode);
break;
return gradient;
【讨论】:
你有这方面的使用例子吗?我不太明白参数应该设置为什么。 当然<effects:GradientEffect Colors="#071c33,#071c33,#030c17" Mode="ToBottomRight" Locations="0,.175,1" />
【参考方案6】:
XFGloss 项目增加了通过 XAML 添加渐变的功能。
例如:
<xfg:ContentPageGloss.BackgroundGradient>
<xfg:Gradient Rotation="150">
<xfg:GradientStep StepColor="White" StepPercentage="0" />
<xfg:GradientStep StepColor="White" StepPercentage=".5" />
<xfg:GradientStep StepColor="#ccd9ff" StepPercentage="1" />
</xfg:Gradient>
</xfg:ContentPageGloss.BackgroundGradient>
...
</ContentPage>
【讨论】:
【参考方案7】:这是我写的一个 ContentView。您可以在没有 CustomRender 的情况下在 PCL/Core 项目中按原样使用。但它依赖于 SkiaSharp。
它有一个 ItemTemplate 和 Bindable 属性。
Xamarin Forms Gradient Content View
【讨论】:
【参考方案8】:Android draw mehtod 不适合我,所以我扩展了一点:
protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
Android.Graphics.LinearGradient gradient;
using (var path = new Android.Graphics.Path())
using(var paint = new Android.Graphics.Paint()
Dither = true,
AntiAlias = true,
)
using (Android.Graphics.Path.Direction direction = Android.Graphics.Path.Direction.Cw)
using (var rect = new Android.Graphics.RectF(0, 0, (float)canvas.Width, (float)canvas.Height))
if (Element.Orientation == StackOrientation.Vertical)
gradient = new Android.Graphics.LinearGradient(0, 0, 0, Height, this.StartColor.ToAndroid(),
this.EndColor.ToAndroid(),
Android.Graphics.Shader.TileMode.Mirror);
else
gradient = new Android.Graphics.LinearGradient(0, 0, Width, 0, this.StartColor.ToAndroid(),
this.EndColor.ToAndroid(),
Android.Graphics.Shader.TileMode.Mirror);
path.AddRect(rect, direction);
paint.SetShader(gradient);
canvas.DrawPath(path, paint);
base.DispatchDraw(canvas);
【讨论】:
【参考方案9】:我编辑了@na2axl 给出的类,以使用它以这种格式“R,G,B,A:R,G,B,A”提供 rbga 颜色。所有颜色将用冒号分隔,它们的值将用 qoma (,) 分隔,例如 "255,255,255,100:255,255,255,0"
public class GradientLayout : StackLayout
public string ColorsList get; set;
public Color[] Colors
get
string[] rgbacolor = ColorsList.Split(':');
Color[] colors = new Color[rgbacolor.Length];
for (int i = 0; i < rgbacolor.Length; i++)
string[] colorcodes = rgbacolor[i].Trim().Split(',');
double r = double.Parse(colorcodes[0].Trim());
double g = double.Parse(colorcodes[1].Trim());
double b = double.Parse(colorcodes[2].Trim());
double a = double.Parse(colorcodes[3].Trim());
colors[i] = Color.FromRgba(r,g,b,a);
//Color.FromHex(rgbacolor[i].Trim());
return colors;
public GradientColorStackMode Mode get; set;
【讨论】:
我在我的应用程序中使用此代码最好的解决方案是https://devblogs.microsoft.com/xamarin/magic-gradients-xamarinforms/ 此处描述的解决方案
安装 nuget MagicGradients
在 app.xaml 中添加一行
<Application.Resources>
<!-- ..... -->
<Style TargetType="ContentPage" ApplyToDerivedTypes="True">
<Setter Property="ControlTemplate">
<Setter.Value>
<ControlTemplate>
<Grid>
<magicGradients:GradientView VerticalOptions="FillAndExpand">
<magicGradients:GradientView.GradientSource>
<magicGradients:LinearGradient Angle="320">
<magicGradients:GradientStop Color="#338af9" Offset="0" />
<magicGradients:GradientStop Color="#2ff8ff" Offset="1" />
</magicGradients:LinearGradient>
</magicGradients:GradientView.GradientSource>
</magicGradients:GradientView>
<ContentPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ..... --->
</Application.Resources>
以上将线性渐变应用到您的 ContentPage
【讨论】:
【参考方案11】:启动 Xamarin Forms 4.8,您可以添加内置渐变。
<Frame BorderColor="LightGray"
HasShadow="True"
CornerRadius="12"
HeightRequest="120"
WidthRequest="120">
<Frame.Background>
<RadialGradientBrush Center="0.5,0.5"
Radius="0.5">
<GradientStop Color="Red"
Offset="0.1"/>
<GradientStop Color="DarkBlue"
Offset="1.0"/>
</RadialGradientBrush>
</Frame.Background>
Microsoft DevBlogs 上的来源和详细信息:https://devblogs.microsoft.com/xamarin/xamarinforms-4-8-gradients-brushes/
【讨论】:
【参考方案12】:要使用动态资源,您必须使您的属性可绑定,像这样
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);
【讨论】:
以上是关于向 Xamarin Forms Visual Studio 中的布局添加渐变背景的主要内容,如果未能解决你的问题,请参考以下文章
共享项目选项完全从 Visual Studio 2019 中的 Xamarin.Forms 项目菜单中消失?
如何更改“Xamarin.Forms Material Visual”禁用按钮的透明度?
如何使用 C++ 非托管库在 Visual Studio 2017 中为 Xamarin.Forms 设置项目?
Xamarin Forms不会在Visual Studio 2017中创建.csproj文件
在 Visual Studio 上运行 Xamarin Forms iOS 时出现 GetBuiltProjectOutputRecursive 错误