Fatikhan Gasimov
Fatikhan Gasimov

Reputation: 943

Gradient stack OnElementPropertyChanged not working in Xamarin Forms

I am trying to change Gradient's background colour from my method but it doesn't work. The background colour comes when the app starts but the problem is that I can't change it after.

My custom GradientColorStackRenderer:

[assembly: ExportRenderer(typeof(GradientColorStack), typeof(GradientColorStackRenderer))]

namespace GradientColor.Droid
{
    
    public class GradientColorStackRenderer : VisualElementRenderer<StackLayout>
    {
        public Color StartColor { get; set; }
        public Color EndColor { get; set; }
        protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
        {
            #region for Vertical Gradient
            var gradient = new Android.Graphics.LinearGradient(0, 0, 0, Height,
            #endregion

            #region for Horizontal Gradient
                    // var gradient = new Android.Graphics.LinearGradient(0, 0, Width, 0,
            #endregion

                    this.StartColor.ToAndroid(),
                    this.EndColor.ToAndroid(),
                    Android.Graphics.Shader.TileMode.Mirror);

            var paint = new Android.Graphics.Paint()
            {
                Dither = true,
            };
            paint.SetShader(gradient);
            canvas.DrawPaint(paint);
            base.DispatchDraw(canvas);
        }

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

            if (e.OldElement != null || Element == null)
            {
                return;
            }
            try
            {
                var stack = e.NewElement as GradientColorStack;
                this.StartColor = stack.StartColor;
                this.EndColor = stack.EndColor;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(@"ERROR:", ex.Message);
            }
        }


        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if (e.PropertyName == "StartColor" || e.PropertyName  == "EndColor")
            {
                var stack = sender as GradientColorStack;
                this.StartColor = stack.StartColor;
                this.EndColor = stack.EndColor;
            }
        }

    }
}

My method

 private void Button_Clicked(object sender, EventArgs e)
        {
          
          
            lytBack.StartColor = Color.Red;
            lytBack.EndColor = Color.Blue;
            lytBack.Opacity = 1;
        }

My XAML

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Randomage.MainPage"
             xmlns:local="clr-namespace:GradientColor; assembly:GradientColor" 
             >

    <local:GradientColorStack  x:Name="lytBack" StartColor="#ffc3a0" EndColor="#ffafbd"   Spacing="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
  
    </local:GradientColorStack>
</ContentPage>

The background colour comes when the app starts but the problem is that I can't change it after. The background colour comes when the app starts but the problem is that I can't change it after.

Upvotes: 0

Views: 164

Answers (1)

Pete
Pete

Reputation: 4746

Your detecting the property changes in your Android Renderer, however you are not issuing a re-paint to occur, so that these can be used.

Change:-

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
        if (e.PropertyName == "StartColor" || e.PropertyName  == "EndColor")
        {
            var stack = sender as GradientColorStack;
            this.StartColor = stack.StartColor;
            this.EndColor = stack.EndColor;
        }
    }

to:-

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
        if (e.PropertyName == "StartColor" || e.PropertyName  == "EndColor")
        {
            var stack = sender as GradientColorStack;
            this.StartColor = stack.StartColor;
            this.EndColor = stack.EndColor;
            //
            this.Invalidate();
        }
    }

this.Invalidate() forces the repaint to occur.

Upvotes: 1

Related Questions