Xamarin.forms 将渐变设置为按钮颜色渲染器

Xamarin.forms 将渐变设置为按钮颜色渲染器,xamarin.forms,Xamarin.forms,我使用的是Xamarin.Forms,我试图将渐变设置为按钮颜色。 我和这家伙的问题完全一样: 但给出的答案并不完全是我想要的 答案是成功的,但它将所有按钮设置为渐变 例如:这家伙有个问题,只画了背景,给出的答案设置了整个按钮,我想设置按钮本身的颜色并保留填充 我可能知道为什么代码不起作用,如何使用答案并使其起作用?? 编辑: 这是我的密码: public class GenericButton:Button { public Xamarin.Forms.Color StartColor

我使用的是Xamarin.Forms,我试图将渐变设置为按钮颜色。 我和这家伙的问题完全一样:

但给出的答案并不完全是我想要的

答案是成功的,但它将所有按钮设置为渐变

例如:这家伙有个问题,只画了背景,给出的答案设置了整个按钮,我想设置按钮本身的颜色并保留填充

我可能知道为什么代码不起作用,如何使用答案并使其起作用?? 编辑: 这是我的密码:

public class GenericButton:Button
{
    public Xamarin.Forms.Color StartColor { get; set; }
    public Xamarin.Forms.Color EndColor { get; set; }
}
有了这段代码,我得到了按钮之外的回溯:

public class GenericButtonRenderer :ButtonRenderer
{
    private Xamarin.Forms.Color StartColor { get; set; }
    private Xamarin.Forms.Color EndColor { get; set; }

    protected override void DispatchDraw(Canvas canvas)
    {
        var gradient = new Android.Graphics.LinearGradient(0, 0, Width, Height,
            this.StartColor.ToAndroid(),
            this.EndColor.ToAndroid(),
            Android.Graphics.Shader.TileMode.Clamp);
        var paint = new Android.Graphics.Paint()
        {
            Dither = true,
        };
        paint.SetShader(gradient);
        canvas.DrawPaint(paint);
        base.DispatchDraw(canvas);
    }

    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
    {
        base.OnElementChanged(e);
        if (e.OldElement != null || Element == null)
        {
            return;
        }
        try
        {
            var btn = e.NewElement as GenericButton;
            this.StartColor = btn.StartColor;
            this.EndColor = btn.EndColor;                
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(@"          ERROR: ", ex.Message);
        }
    }
}//See result here: http://i.stack.imgur.com/3ZpuX.png
公共类GenericButtonRenderer:ButtonRenderer
{
private Xamarin.Forms.Color StartColor{get;set;}
私有Xamarin.Forms.Color EndColor{get;set;}
受保护的覆盖无效DispatchDraw(画布)
{
var gradient=new Android.Graphics.LinearGradient(0,0,宽度,高度,
this.StartColor.ToAndroid(),
this.EndColor.ToAndroid(),
Android.Graphics.Shader.TileMode.Clamp);
var paint=new Android.Graphics.paint()
{
抖动=正确,
};
油漆.固色剂(梯度);
帆布.拉丝漆(油漆);
base.DispatchDraw(画布);
}
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
if(e.OldElement!=null | | Element==null)
{
返回;
}
尝试
{
var btn=e.NewElement作为GenericButton;
this.StartColor=btn.StartColor;
this.EndColor=btn.EndColor;
}
捕获(例外情况除外)
{
System.Diagnostics.Debug.WriteLine(@“错误:”,例如消息);
}
}
}//请参见此处的结果:http://i.stack.imgur.com/3ZpuX.png
第二件事我尝试了,用这个我得到了正确的梯度,但按钮失去了它的布局:

public class GenericButtonRenderer :ButtonRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
    {
        base.OnElementChanged(e);
        if (e.OldElement != null || Element == null)
        {
            return;
        }
        try
        {
            var btn = e.NewElement as GenericButton;
            var gradient = new GradientDrawable(GradientDrawable.Orientation.TopBottom, new[] {
            btn.StartColor.ToAndroid().ToArgb(),
           btn.EndColor.ToAndroid().ToArgb()
        });
            Control.Background=gradient;                
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(@"          ERROR: ", ex.Message);
        }
    }
}//See result here: http://i.stack.imgur.com/4CDtG.png
公共类GenericButtonRenderer:ButtonRenderer
{
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
if(e.OldElement!=null | | Element==null)
{
返回;
}
尝试
{
var btn=e.NewElement作为GenericButton;
var gradient=新的GradientDrawable(GradientDrawable.Orientation.TopBottom,新[]{
btn.StartColor.ToAndroid().ToArgb(),
btn.EndColor.ToAndroid().ToArgb()
});
背景=梯度;
}
捕获(例外情况除外)
{
System.Diagnostics.Debug.WriteLine(@“错误:”,例如消息);
}
}
}//请参见此处的结果:http://i.stack.imgur.com/4CDtG.png

我找到了一个不完全是我想要的解决方法,我会一直这样做,直到我找到更好的答案为止(这个方法不再适用)

所以我的按钮在一个网格内,它们是网格的唯一组成部分,所以我只是在网格中添加了以下内容,按钮不会出现在屏幕底部。(但顶部填充物不起作用。)


我还不会选择这个答案,因为我仍然希望有人能找到更好的解决方案。

您需要扩展ButtonRenderer并自定义本机控件的Background属性

/// <summary>
    /// Extends <see cref="Xamarin.Forms.Button"/>.
    /// </summary>
    public class ExtendedButton : Button
    {
        /// <summary>
        /// Bindable property for button background gradient start color
        /// </summary>
        public static readonly BindableProperty StartColorProperty =
            BindableProperty.Create("StartColor", typeof(Color), typeof(ExtendedButton), Color.Gray); 

        /// <summary>
        /// Gets or sets the background gradient start color
        /// </summary>
        public Color StartColor 
        {
            get { return (Color)this.GetValue(StartColorProperty); }
            set { this.SetValue(StartColorProperty, value); }
        }

        /// <summary>
        /// Bindable property for button background gradient end color
        /// </summary>
        public static readonly BindableProperty EndColorProperty =
            BindableProperty.Create("EndColor", typeof(Color), typeof(ExtendedButton), Color.Black);  

        /// <summary>
        /// Gets or sets the background gradient end color
        /// </summary>
        public Color EndColor
        {
            get { return (Color)this.GetValue(EndColorProperty); }
            set { this.SetValue(EndColorProperty, value); }
        }
    }

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Graphics.Drawables;

using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

using NewHelloWorld.Droid.Renderers;
using NewHelloWorld;



[assembly: ExportRenderer(typeof(ExtendedButton), typeof(ExtendedButtonRenderer))]
namespace NewHelloWorld.Droid.Renderers
{
    /// <summary>
    /// Class ExtendedButtonRenderer.
    /// </summary>
    public class ExtendedButtonRenderer : ButtonRenderer
    {
        /// <summary>
        /// Called when [element changed].
        /// </summary>
        /// <param name="e">The e.</param>
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);
            UpdateGradientBackground();
        }

        /// <summary>
        /// Handles the <see cref="E:ElementPropertyChanged" /> event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param>
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if(e.PropertyName == ExtendedButton.StartColorProperty.PropertyName || 
                e.PropertyName == ExtendedButton.EndColorProperty.PropertyName || 
                e.PropertyName == ExtendedButton.BorderColorProperty.PropertyName ||
                e.PropertyName == ExtendedButton.BorderRadiusProperty.PropertyName ||
                e.PropertyName == ExtendedButton.BorderWidthProperty.PropertyName)
            {
                UpdateGradientBackground();
            }

            base.OnElementPropertyChanged(sender, e);
        }

        //Called 
        protected override void UpdateBackgroundColor()
        {
            base.UpdateBackgroundColor();

            UpdateGradientBackground();
        }

        //Sets the background gradient color
        private void UpdateGradientBackground()
        {
            var button = this.Element as ExtendedButton;
            if (button != null)
            {
                int[] colors = new int[] { button.StartColor.ToAndroid(), button.EndColor.ToAndroid() };
                var gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TopBottom, colors);
                gradientDrawable.SetGradientType(GradientType.LinearGradient);
                gradientDrawable.SetShape(ShapeType.Rectangle);
                gradientDrawable.SetCornerRadius(button.BorderRadius);
                gradientDrawable.SetStroke((int)button.BorderWidth, button.BorderColor.ToAndroid());
                this.Control.Background = gradientDrawable;
            }
        }
    }
}
//
///延伸。
/// 
公共类扩展按钮:按钮
{
/// 
///按钮背景渐变开始颜色的可绑定属性
/// 
公共静态只读BindableProperty StartColorProperty=
创建(“StartColor”、typeof(Color)、typeof(ExtendedButton)、Color.Gray);
/// 
///获取或设置背景渐变开始颜色
/// 
公共色星色
{
获取{return(Color)this.GetValue(startColor属性);}
set{this.SetValue(startColor属性,值);}
}
/// 
///按钮背景渐变结束颜色的可绑定属性
/// 
公共静态只读BindableProperty EndColorProperty=
创建(“EndColor”、typeof(Color)、typeof(ExtendedButton)、Color.Black);
/// 
///获取或设置背景渐变结束颜色
/// 
公共色底色
{
获取{return(Color)this.GetValue(EndColorProperty);}
set{this.SetValue(EndColorProperty,value);}
}
}
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统组件模型;
使用Android.App;
使用Android.Content;
使用Android.OS;
使用Android.Runtime;
使用Android.Views;
使用Android.Widget;
使用Android.Graphics.Drawables;
使用Xamarin.Forms;
使用Xamarin.Forms.Platform.Android;
使用NewHelloWorld.Droid.renders;
使用NewHelloWorld;
[程序集:ExportRenderer(typeof(ExtendedButton)、typeof(ExtendedButtonRenderer))]
命名空间NewHelloWorld.Droid.Renderers
{
/// 
///类ExtendedButtonRenderer。
/// 
公共类扩展ButtonRenderer:ButtonRenderer
{
/// 
///在[element changed]时调用。
/// 
///e。
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
UpdateGradientBackground();
}
/// 
///处理事件。
/// 
///发送者。
///包含事件数据的实例。
受保护的覆盖无效OnElementPropertyChanged(对象发送方,PropertyChangedEventArgs e)
{
如果(e.PropertyName==ExtendedButton.StartColorProperty.PropertyName | |
e、 PropertyName==ExtendedButton.EndColorProperty.PropertyName | |
e、 PropertyName==ExtendedButton.BorderColorProperty.PropertyName||
e、 PropertyName==扩展
/// <summary>
    /// Extends <see cref="Xamarin.Forms.Button"/>.
    /// </summary>
    public class ExtendedButton : Button
    {
        /// <summary>
        /// Bindable property for button background gradient start color
        /// </summary>
        public static readonly BindableProperty StartColorProperty =
            BindableProperty.Create("StartColor", typeof(Color), typeof(ExtendedButton), Color.Gray); 

        /// <summary>
        /// Gets or sets the background gradient start color
        /// </summary>
        public Color StartColor 
        {
            get { return (Color)this.GetValue(StartColorProperty); }
            set { this.SetValue(StartColorProperty, value); }
        }

        /// <summary>
        /// Bindable property for button background gradient end color
        /// </summary>
        public static readonly BindableProperty EndColorProperty =
            BindableProperty.Create("EndColor", typeof(Color), typeof(ExtendedButton), Color.Black);  

        /// <summary>
        /// Gets or sets the background gradient end color
        /// </summary>
        public Color EndColor
        {
            get { return (Color)this.GetValue(EndColorProperty); }
            set { this.SetValue(EndColorProperty, value); }
        }
    }

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Graphics.Drawables;

using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

using NewHelloWorld.Droid.Renderers;
using NewHelloWorld;



[assembly: ExportRenderer(typeof(ExtendedButton), typeof(ExtendedButtonRenderer))]
namespace NewHelloWorld.Droid.Renderers
{
    /// <summary>
    /// Class ExtendedButtonRenderer.
    /// </summary>
    public class ExtendedButtonRenderer : ButtonRenderer
    {
        /// <summary>
        /// Called when [element changed].
        /// </summary>
        /// <param name="e">The e.</param>
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);
            UpdateGradientBackground();
        }

        /// <summary>
        /// Handles the <see cref="E:ElementPropertyChanged" /> event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param>
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if(e.PropertyName == ExtendedButton.StartColorProperty.PropertyName || 
                e.PropertyName == ExtendedButton.EndColorProperty.PropertyName || 
                e.PropertyName == ExtendedButton.BorderColorProperty.PropertyName ||
                e.PropertyName == ExtendedButton.BorderRadiusProperty.PropertyName ||
                e.PropertyName == ExtendedButton.BorderWidthProperty.PropertyName)
            {
                UpdateGradientBackground();
            }

            base.OnElementPropertyChanged(sender, e);
        }

        //Called 
        protected override void UpdateBackgroundColor()
        {
            base.UpdateBackgroundColor();

            UpdateGradientBackground();
        }

        //Sets the background gradient color
        private void UpdateGradientBackground()
        {
            var button = this.Element as ExtendedButton;
            if (button != null)
            {
                int[] colors = new int[] { button.StartColor.ToAndroid(), button.EndColor.ToAndroid() };
                var gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TopBottom, colors);
                gradientDrawable.SetGradientType(GradientType.LinearGradient);
                gradientDrawable.SetShape(ShapeType.Rectangle);
                gradientDrawable.SetCornerRadius(button.BorderRadius);
                gradientDrawable.SetStroke((int)button.BorderWidth, button.BorderColor.ToAndroid());
                this.Control.Background = gradientDrawable;
            }
        }
    }
}