Xamarin.Forms在iOS上使用Custom Renderer的Button渐变背景
我正在使用Xamarin.Forms,并且希望全局使按钮看起来更好看.
I am using Xamarin.Forms and I want to globally make the buttons look a little nicer.
我已经使用自定义渲染器在Android版本上实现了这一点,但是在iOS上却遇到了同样的问题.
I have achieved this just fine for the Android version using a custom renderer, but I am having trouble doing the same with iOS.
在XAML页面中定义按钮时,我引用"CustomButton"而不是"Button",然后在我的iOS应用中具有以下CustomButtonRenderer.
When defining buttons in my XAML pages, I reference "CustomButton" instead of "Button", and then I have the following CustomButtonRenderer in my iOS app.
大多数样式更改都可以正常工作(边界半径等),但是我似乎无法使它呈现按钮的背景渐变.
Most of the style changes work just fine (border radius, etc), but I cannot seem to make it render a background gradient for the button.
到目前为止,这是我的代码,但是背景只是显示为白色.如何使它的顶部显示渐变色?
Here is my code so far, but the background just displays as white. How can I make it display a gradient with the text on top?
class CustomButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (Control != null)
{
var gradient = new CAGradientLayer();
gradient.Frame = Control.Layer.Bounds;
gradient.Colors = new CGColor[]
{
UIColor.FromRGB(51, 102, 204).CGColor,
UIColor.FromRGB(51, 102, 204).CGColor
};
Control.Layer.AddSublayer(gradient);
Control.Layer.CornerRadius = 10;
Control.Layer.BorderColor = UIColor.FromRGB(51, 102, 204).CGColor;
Control.Layer.BorderWidth = 1;
Control.VerticalAlignment = UIControlContentVerticalAlignment.Center;
}
}
}
1st)不要使用AddSublayer
,请使用InsertSublayerBelow
,这样Z顺序将正确并且您的
1st) Do not use AddSublayer
, use InsertSublayerBelow
so that the Z-order will be correct and your Title
text will be on top.
第二个)覆盖LayoutSubviews
并更新您的CAGradientLayer
框架以匹配您的UIButton
.
2nd) Override LayoutSubviews
and update your CAGradientLayer
frame to match your UIButton
.
3rd):尽情享受渐变效果
[assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))]
namespace AppCompatRender.iOS
{
public class CustomButtonRenderer : Xamarin.Forms.Platform.iOS.ButtonRenderer
{
public override void LayoutSubviews()
{
foreach (var layer in Control?.Layer.Sublayers.Where(layer => layer is CAGradientLayer))
layer.Frame = Control.Bounds;
base.LayoutSubviews();
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
var gradient = new CAGradientLayer();
gradient.CornerRadius = Control.Layer.CornerRadius = 10;
gradient.Colors = new CGColor[]
{
UIColor.FromRGB(51, 102, 104).CGColor,
UIColor.FromRGB(51, 202, 204).CGColor
};
var layer = Control?.Layer.Sublayers.LastOrDefault();
Control?.Layer.InsertSublayerBelow(gradient, layer);
}
}
}
}
更新:
如果您将iOS 10+ 与的新版本Xamarin.Forms
一起使用,则在调用LayoutSubViews
时的Control.Bounds
将全部为零.在设置控件的Frame
属性的过程中,您需要设置渐变层Frame
的大小,即:
Update:
If you are using iOS 10+ with newer version of Xamarin.Forms
, the Control.Bounds
during calls to LayoutSubViews
will all be zeros. You will need to set the gradient layer Frame
size during sets to the control's Frame
property, i.e.:
public class CustomButtonRenderer : Xamarin.Forms.Platform.iOS.ButtonRenderer
{
public override CGRect Frame
{
get
{
return base.Frame;
}
set
{
if (value.Width > 0 && value.Height > 0)
{
foreach (var layer in Control?.Layer.Sublayers.Where(layer => layer is CAGradientLayer))
layer.Frame = new CGRect(0, 0, value.Width, value.Height);
}
base.Frame = value;
}
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
var gradient = new CAGradientLayer();
gradient.CornerRadius = Control.Layer.CornerRadius = 20;
gradient.Colors = new CGColor[]
{
UIColor.FromRGB(51, 102, 104).CGColor,
UIColor.FromRGB(51, 202, 204).CGColor
};
var layer = Control?.Layer.Sublayers.LastOrDefault();
Control?.Layer.InsertSublayerBelow(gradient, layer);
}
}
}