我正在使用Xamarin.Forms,我希望全局使按钮看起来更好一些。
对于使用自定义渲染器的Android版本,我已经达到了这个目的,但我在使用iOS时也遇到了麻烦。
在我的XAML页面中定义按钮时,我引用“CustomButton”而不是“Button”,然后我的iOS应用程序中有以下CustomButtonRenderer。
大多数样式更改工作得很好(边框半径等),但我似乎无法使其呈现按钮的背景渐变。
到目前为止,这是我的代码,但背景只显示为白色。如何让它显示顶部带有文字的渐变?
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;
}
}
}
答案 0 :(得分:7)
1st)请勿使用AddSublayer
,请使用InsertSublayerBelow
,以便Z顺序正确并且您的Title
文字将位于首位。
第二次:覆盖LayoutSubviews
并更新您的CAGradientLayer
框架以匹配您的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);
}
}
}
}
如果您使用的是带有较新版Xamarin.Forms
的iOS 10+ ,则Control.Bounds
来电期间LayoutSubViews
将全部为零。您需要在集合期间将梯度图层Frame
的大小设置为控件的Frame
属性,即:
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);
}
}
}
答案 1 :(得分:0)
在调用OnElementChanged时,Control.Layer.Bounds
完全为零。在渲染中,您需要添加方法来更新渐变框架,以匹配Control.Layer的框架。
答案 2 :(得分:0)
回应罗伯特·卡法佐(Robert Cafazzo)的评论,我可以帮助稍微调整此渲染,使其正常工作:
public class GdyBtnRendererIos : ButtonRenderer
{
#region Colors
static Color rosecolor = (Color)App.Current.Resources["ClrGeneralrose"];
static Color orangecolor = (Color)App.Current.Resources["ClrRoseOrange"];
CGColor roseCGcolor = rosecolor.ToCGColor();
CGColor orangeCGcolor = orangecolor.ToCGColor();
#endregion
CAGradientLayer gradient;
public override CGRect Frame
{
get => base.Frame;
set
{
if (value.Width > 0 && value.Height > 0)
{
if (Control?.Layer.Sublayers != null)
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 OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "Renderer")
{
gradient.Frame = new CGRect(0, 0, Frame.Width, Frame.Height);
}
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.OldElement != null) return;
gradient = new CAGradientLayer
{
CornerRadius = Control.Layer.CornerRadius,
Colors = new CGColor[] { roseCGcolor, orangeCGcolor },
StartPoint = new CGPoint(0.1, 0.5),
EndPoint = new CGPoint(1.1, 0.5)
};
var layer = Control?.Layer.Sublayers.LastOrDefault();
Control?.Layer.InsertSublayerBelow(gradient, layer);
base.Draw(Frame);
}