0
votes

I am creating a button with a gradient in Xamarin forms. I am successfully making it but when i later on in the code try to update its color, nothing happens in the UI.

This is how the project is setup:

XAML:

<controls:FullyColoredGradient x:Name = "SelectedBackground" StartColor = "Purple" EndColor="Yellow" /> 

If i then later on the code do a void and try to update these colors like this:

SelectedBackground.EndColor = Color.Red;
SelectedBackground.StartColor = Color.Blue;

Then nothing happens. They do not recolor.

This is how my shared code looks:

public class FullyColoredGradient : Button
{
    public static readonly BindableProperty StartColorProperty =
    BindableProperty.Create(nameof(StartColor),
    typeof(Color), typeof(FullyColoredGradient),
    Color.Default);

    public Color StartColor
    {
        get { return (Color)GetValue(StartColorProperty); }
        set { SetValue(StartColorProperty, value); }
    }


    public static readonly BindableProperty EndColorProperty =
    BindableProperty.Create(nameof(EndColor),
    typeof(Color), typeof(FullyColoredGradient),
    Color.Default);

    public Color EndColor
    {
        get { return (Color)GetValue(EndColorProperty); }
        set { SetValue(EndColorProperty, value); }
    }
}

And this is my iOS renderer:

public class TransparentGradientColor_iOS : ButtonRenderer
{
    CGRect rect;
    CAGradientLayer gradientLayer;

    public TransparentGradientColor_iOS() { }
    public override void Draw(CGRect rect)
    {
        base.Draw(rect);
        this.rect = rect;

        FullyColoredGradient rcv = (FullyColoredGradient)Element;
        if (rcv == null)
            return;

        this.ClipsToBounds = true;
        this.Layer.MasksToBounds = true;

        FullyColoredGradient stack = (FullyColoredGradient)this.Element;

        CGColor startColor = stack.StartColor.ToCGColor();
        CGColor endColor = stack.EndColor.ToCGColor();

        #region for Vertical Gradient

        this.gradientLayer = new CAGradientLayer()
        {
            StartPoint = new CGPoint(0, 0.5),
            EndPoint = new CGPoint(1, 0.5)
        };
        #endregion

        gradientLayer.Frame = rect;
        gradientLayer.Colors = new CGColor[] { startColor, endColor };

        NativeView.Layer.InsertSublayer(gradientLayer, 0);
    }

    protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
    {
        base.OnElementChanged(e);

        if (e.OldElement == null)
        {
            UpdateColor();
        }
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
        UpdateColor();
    }

    void UpdateColor()
    {
        if (gradientLayer != null)
        {
            FullyColoredGradient stack = (FullyColoredGradient)this.Element;

            CGColor startColor = Xamarin.Forms.Color.White.ToCGColor();
            CGColor endColor = Xamarin.Forms.Color.White.ToCGColor();

            gradientLayer.Colors = new CGColor[] { startColor, endColor };
        }
    }
}
1

1 Answers

0
votes

I have used this custom renderer, this will apply gradient to all buttons(you can create custom button if you want), you can try this out:

[assembly: ExportRenderer(typeof(Button), typeof(CustomButtonRendereriOS))]

namespace XYZ.iOS.Renderer
{
  public class CustomButtonRendereriOS : ButtonRenderer
   {
    //To apply gradient background to button
    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)
        {
            try
            {
                    var gradient = new CAGradientLayer();
                    gradient.CornerRadius = Control.Layer.CornerRadius = 5;
                    gradient.Colors = new CGColor[]
                    {
                        UIColor.FromRGB(243, 112, 33).CGColor,
                        UIColor.FromRGB(226, 64, 64).CGColor
                    };
                    var layer = Control?.Layer.Sublayers.LastOrDefault();
                    Control?.Layer.InsertSublayerBelow(gradient, layer);

            }
            catch (Exception ex)
            {


            }

        }
    }

}

You can also use a gradient stack layout/ Frame as described here with help of custom renderer and use Tap Gesture of it for clicked event. Gradient Button in Xamarin Forms Hope this may solve your issue.