Xamarin 形成 Android 的渐变按钮
Xamarin Forms Gradient Button for Android
我已经为我的 Xamarin.Forms Android 应用程序实现了自定义渲染器,以具有渐变背景按钮。渐变效果很好,但它被绘制在我的按钮及其文本上,我不知道如何在按钮后面绘制它。
自定义 Android 渲染器:
[assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))]
namespace MyApp.Droid
{
public class CustomButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer
{
public CustomButtonRenderer(Context context) : base(context)
{
}
protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
{
base.DispatchDraw(canvas);
var gradient = new Android.Graphics.LinearGradient(0, 0, 0, Height,
Color.FromRgba(255, 239, 124, 255).ToAndroid(),
Color.FromRgba(239, 210, 0, 50).ToAndroid(),
Android.Graphics.Shader.TileMode.Repeat);
var paint = new Android.Graphics.Paint()
{
Dither = true,
};
paint.SetShader(gradient);
canvas.DrawPaint(paint);
}
}
}
我认为这里不需要单独的渲染器,
你可以这样做:
Resources/drawable/gradient.xml
在此处添加您的渐变设计
<?xml version="1.0" encoding="utf-8" ?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="45"
android:startColor="#80D776"
android:endColor="#71D6C5"
android:type="linear"/>
<corners
android:bottomLeftRadius="40dp"
android:bottomRightRadius="40dp"
android:topLeftRadius="40dp"
android:topRightRadius="40dp" />
<padding
android:left="3dp"
android:top="8dp"
android:right="3dp"
android:bottom="8dp" />
</shape>
如果它是一个通用按钮,您需要在应用程序中随处使用,然后在您的 Resouces/values/styles.xml
<style name="Widget.Button" parent="Theme.AppCompat">
<item name="android:background">@drawable/gradient</item>
<item name="android:focusable">true</item>
<item name="android:clickable">true</item>
<item name="android:textColor">@color/primary</item>
<item name="android:textAppearance">?android:attr/textAppearanceSmallInverse</item>
<item name="android:gravity">center_vertical|center_horizontal</item>
</style>
我写了一个demo,通过Custom Renderer
实现
这是该演示的 GIF。
Android 渲染器
[assembly: ExportRenderer(typeof(MyButton), typeof(GradientButtonRenderer))]
namespace GradientButton.Droid.Renderers
{
public class GradientButtonRenderer : ButtonRenderer
{
public GradientButtonRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
var btn = this.Control as Android.Widget.Button;
btn?.SetBackgroundResource(Resource.Drawable.gradient_button_style);
}
}
}
gradient_button_style
<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape>
<solid android:color="#1E90FF" />
<corners android:radius="20dp" />
<padding android:left="10dp" android:top="10dp" android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
<item>
<shape>
<gradient android:startColor="#1E90FF" android:endColor="#00BFFF"
android:angle="0" />
<corners android:radius="20dp" />
<padding android:left="10dp" android:top="10dp" android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
</selector>
这些选项卡的含义
[shape]根标签,声明一个shape
[gradient] 声明形状的属性——渐变,此外还有其他属性,如角、笔触、大小等
[android:angle] 渐变颜色的角度,比如0表示从上到下渐变; 45代表从左到右的渐变; 90表示从下到上的渐变...
[android:startColor&android:endColor]很好理解渐变的颜色和渐变结束时的颜色(从什么颜色到什么颜色)
MyButton
public class MyButton:Button
{
}
IOS 渲染器。
[assembly: ExportRenderer(typeof(MyButton), typeof(GradientButtonRenderer))]
namespace GradientButton.iOS.Renderers
{
public class GradientButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
var gradient = new CAGradientLayer()
{
StartPoint = new CGPoint(0, 0.5),
EndPoint = new CGPoint(1, 0.5)
};
gradient.Locations = new NSNumber[] { .0f, 1f };
gradient.CornerRadius = Element.CornerRadius;
gradient.NeedsDisplayOnBoundsChange = true;
gradient.MasksToBounds = true;
gradient.Colors = new CGColor[]
{
UIColor.FromRGB(30 ,144, 255).CGColor,
UIColor.FromRGB(0 ,191, 255).CGColor
};
var layer = Control?.Layer.Sublayers.FirstOrDefault();
Control?.Layer.InsertSublayerBelow(gradient, layer);
}
}
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;
}
}
}
}
我已经为我的 Xamarin.Forms Android 应用程序实现了自定义渲染器,以具有渐变背景按钮。渐变效果很好,但它被绘制在我的按钮及其文本上,我不知道如何在按钮后面绘制它。
自定义 Android 渲染器:
[assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))]
namespace MyApp.Droid
{
public class CustomButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer
{
public CustomButtonRenderer(Context context) : base(context)
{
}
protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
{
base.DispatchDraw(canvas);
var gradient = new Android.Graphics.LinearGradient(0, 0, 0, Height,
Color.FromRgba(255, 239, 124, 255).ToAndroid(),
Color.FromRgba(239, 210, 0, 50).ToAndroid(),
Android.Graphics.Shader.TileMode.Repeat);
var paint = new Android.Graphics.Paint()
{
Dither = true,
};
paint.SetShader(gradient);
canvas.DrawPaint(paint);
}
}
}
我认为这里不需要单独的渲染器, 你可以这样做:
Resources/drawable/gradient.xml
在此处添加您的渐变设计
<?xml version="1.0" encoding="utf-8" ?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="45"
android:startColor="#80D776"
android:endColor="#71D6C5"
android:type="linear"/>
<corners
android:bottomLeftRadius="40dp"
android:bottomRightRadius="40dp"
android:topLeftRadius="40dp"
android:topRightRadius="40dp" />
<padding
android:left="3dp"
android:top="8dp"
android:right="3dp"
android:bottom="8dp" />
</shape>
如果它是一个通用按钮,您需要在应用程序中随处使用,然后在您的 Resouces/values/styles.xml
<style name="Widget.Button" parent="Theme.AppCompat">
<item name="android:background">@drawable/gradient</item>
<item name="android:focusable">true</item>
<item name="android:clickable">true</item>
<item name="android:textColor">@color/primary</item>
<item name="android:textAppearance">?android:attr/textAppearanceSmallInverse</item>
<item name="android:gravity">center_vertical|center_horizontal</item>
</style>
我写了一个demo,通过Custom Renderer
这是该演示的 GIF。
Android 渲染器
[assembly: ExportRenderer(typeof(MyButton), typeof(GradientButtonRenderer))]
namespace GradientButton.Droid.Renderers
{
public class GradientButtonRenderer : ButtonRenderer
{
public GradientButtonRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
var btn = this.Control as Android.Widget.Button;
btn?.SetBackgroundResource(Resource.Drawable.gradient_button_style);
}
}
}
gradient_button_style
<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape>
<solid android:color="#1E90FF" />
<corners android:radius="20dp" />
<padding android:left="10dp" android:top="10dp" android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
<item>
<shape>
<gradient android:startColor="#1E90FF" android:endColor="#00BFFF"
android:angle="0" />
<corners android:radius="20dp" />
<padding android:left="10dp" android:top="10dp" android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
</selector>
这些选项卡的含义
[shape]根标签,声明一个shape
[gradient] 声明形状的属性——渐变,此外还有其他属性,如角、笔触、大小等
[android:angle] 渐变颜色的角度,比如0表示从上到下渐变; 45代表从左到右的渐变; 90表示从下到上的渐变...
[android:startColor&android:endColor]很好理解渐变的颜色和渐变结束时的颜色(从什么颜色到什么颜色)
MyButton
public class MyButton:Button
{
}
IOS 渲染器。
[assembly: ExportRenderer(typeof(MyButton), typeof(GradientButtonRenderer))]
namespace GradientButton.iOS.Renderers
{
public class GradientButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
var gradient = new CAGradientLayer()
{
StartPoint = new CGPoint(0, 0.5),
EndPoint = new CGPoint(1, 0.5)
};
gradient.Locations = new NSNumber[] { .0f, 1f };
gradient.CornerRadius = Element.CornerRadius;
gradient.NeedsDisplayOnBoundsChange = true;
gradient.MasksToBounds = true;
gradient.Colors = new CGColor[]
{
UIColor.FromRGB(30 ,144, 255).CGColor,
UIColor.FromRGB(0 ,191, 255).CGColor
};
var layer = Control?.Layer.Sublayers.FirstOrDefault();
Control?.Layer.InsertSublayerBelow(gradient, layer);
}
}
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;
}
}
}
}