.netanimationmauilinear-gradients

Animate gradient brush in .NET MAUI?


So, I'm trying to create a border with animated gradient colors and archive a rgb effect. Somehow the color is just static(like in the picture below), it doesn't animate at all and this is where i need some help. The docs are limited and literally don't explain anything about this, like WPF docs would: Static color gradient

The simple code i used:

private LinearGradientBrush gradientBrush;
private Border brd;

public MainPage()
{
    InitializeComponent();

    gradientBrush = new LinearGradientBrush
    {
        StartPoint = new Point(0, 0),
        EndPoint = new Point(1, 0),
        GradientStops = new GradientStopCollection
        {
            new GradientStop { Color = Colors.Red, Offset = 0.0f },
            new GradientStop { Color = Colors.Green, Offset = 0.5f },
            new GradientStop { Color = Colors.Blue, Offset = 1.0f }
        }
    };

    brd = new Border
    {
        StrokeThickness = 5,
        BackgroundColor = Colors.White,
        Stroke = gradientBrush,
        Padding = 10,
        Content = new Label
        {
            Text = "Hello",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center,
            TextColor = Colors.Black,
        }
    };

    Content = new Grid
    {
        Children = { brd }
    };


}

private async void AnimateGradient()
{
    while (true)
    {
        await Task.WhenAll(
            AnimateColor(gradientBrush.GradientStops[0], Colors.Red, Colors.Purple, 2000),
            AnimateColor(gradientBrush.GradientStops[1], Colors.Green, Colors.Yellow, 2000),
            AnimateColor(gradientBrush.GradientStops[2], Colors.Blue, Colors.Cyan, 2000)
        );

        await Task.WhenAll(
            AnimateColor(gradientBrush.GradientStops[0], Colors.Purple, Colors.Red, 2000),
            AnimateColor(gradientBrush.GradientStops[1], Colors.Yellow, Colors.Green, 2000),
            AnimateColor(gradientBrush.GradientStops[2], Colors.Cyan, Colors.Blue, 2000)
        );
    }
}

private Task AnimateColor(GradientStop gradientStop, Color fromColor, Color toColor, uint duration)
{
    var animation = new Animation(v =>
    {
        gradientStop.Color = new Color(
            (float)(fromColor.Red + v * (toColor.Red - fromColor.Red)),
            (float)(fromColor.Green + v * (toColor.Green - fromColor.Green)),
            (float)(fromColor.Blue + v * (toColor.Blue - fromColor.Blue)),
            (float)(fromColor.Alpha + v * (toColor.Alpha - fromColor.Alpha))
        );
        InvalidateMeasure();
        OnPropertyChanged(nameof(brd));

    });

    animation.Commit(this, gradientStop.GetHashCode().ToString(), length: duration, easing: Easing.Linear);
    OnPropertyChanged(nameof(gradientBrush));
    return Task.Delay((int)duration);
}

    protected override async void OnAppearing()
    {
        base.OnAppearing();
        AnimateGradient();
    }

Debugged and tested, code does execute.


Solution

  • I can reproduce the question based on your code. You may raise an issue on GitHub. But if you apply animated gradient color on Border.Background instead of Border.Stroke, it does work.

    So, as a workaround you may nest a smaller Border(or other container) in the outer Border. Set the Background of the inner Border to white and the Background of the outer Border to the animated gradient Brush,

            brd = new Border
            {
                Background = gradientBrush,
                Padding = 10,
                Content = new Border
                {
                    Margin = 5,
                    StrokeThickness = 0,
                    BackgroundColor= Colors.White,
                    Content = new Label
                    {
                        Text = "Hello",
                        HorizontalOptions = LayoutOptions.Center,
                        VerticalOptions = LayoutOptions.Center,
                        TextColor = Colors.Black,
                    }
                }              
            };