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

时间:2016-06-21 13:41:59

标签: xamarin.forms

我正在使用Xamarin.Forms,我试图将渐变设置为按钮颜色。 我和这个家伙有完全相同的问题:Gradient Layer form as the form of a button in Xamarin.Forms Android

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

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

I.E。:这个家伙有一个问题,只有背景画了,给定的答案设置了整个按钮,我想设置按钮本身的颜色并保持填充。

Here我可能有为什么代码不能正常工作,如何使用答案并使这项工作? 编辑: 这是我的代码:

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

我尝试了第二件事,我得到了渐变正确但按钮失去了布局:

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

2 个答案:

答案 0 :(得分:1)

您需要扩展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;
            }
        }
    }
}

答案 1 :(得分:0)

我得到了一个与我正在寻找的解决方法不同的解决方法,直到我找到更好的答案(不再对此有效)。

所以我的按钮位于网格中,它们是网格的唯一组件,所以我只是将以下内容添加到网格中,按钮不会到达屏幕的底部。 (但顶部填充它不起作用。)

Grid grid = new Grid
        {
            VerticalOptions = LayoutOptions.EndAndExpand,
            HorizontalOptions = LayoutOptions.FillAndExpand,
            Padding = new Thickness(5,5,5,5),
            ColumnDefinitions =....

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