Reputation: 2078
I want to animate the gradient of the frame, so it appears to be ping-ponging from one end to the other. Sadly nothing moves but the rest behaves correctly:
GradientStop
Frame
disappears after IsLoading
changes to false
.I checked via breakpoints that all parts of the code are executed. I did one more check and just setting the offset manually in the code behind also has no effect.
How can I get the Offset
moving? I'm running this on a Pixel 5 - API 33 (Android 13.0) emulator builtin into VS 2022.
App.xaml
<?xml version = "1.0" encoding = "UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiMRE"
x:Class="MauiMRE.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
App.xaml.cs
namespace MauiMRE;
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new AppShell();
}
}
AppShell.xaml
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="MauiMRE.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiMRE"
Shell.FlyoutBehavior="Disabled">
<ShellContent
Title="Home"
ContentTemplate="{DataTemplate local:MainPage}"
Route="MainPage" />
</Shell>
AppShell.xaml.cs
namespace MauiMRE;
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
}
}
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiMRE.MainPage"
Title="Animation Example">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Frame IsVisible="{Binding IsLoading}" MinimumHeightRequest="40">
<Frame.Background>
<RadialGradientBrush Center="1.0,1.0">
<GradientStop Color="Gray" x:Name="GradientStop"
Offset="0.0" />
<GradientStop Color="White"
Offset="1.0" />
</RadialGradientBrush>
</Frame.Background>
</Frame>
</Grid>
</ContentPage>
MainPage.xaml.cs
namespace MauiMRE;
public partial class MainPage : ContentPage
{
readonly MainPageVM mainPageVM;
readonly Animation loadingAnimation;
public MainPage(MainPageVM vm)
{
mainPageVM = vm;
InitializeComponent();
BindingContext = vm;
loadingAnimation = new Animation(
v => { GradientStop.Offset = (float)(1 - Math.Abs(v - 1)); }, 0, 2, Easing.Linear
);
GradientStop.Color = Microsoft.Maui.Graphics.Color.FromArgb("#0000ff"); // color changes
GradientStop.Offset = 0.3f; // offset doesn't change
vm.PropertyChanged += Vm_PropertyChanged;
}
protected override void OnAppearing()
{
mainPageVM.Load();
base.OnAppearing();
}
private void Vm_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(mainPageVM.IsLoading))
{
var animationId = "loadingAnimation";
if (mainPageVM.IsLoading)
{
loadingAnimation.Commit(this, animationId, 16, 1000, Easing.Linear, (v, c) => { GradientStop.Offset = 0; }, () => { return true; });
}
else
{
_ = this.AbortAnimation(animationId);
}
}
}
}
MainPageVM.cs
using CommunityToolkit.Mvvm.ComponentModel;
namespace MauiMRE;
public partial class MainPageVM : ObservableObject
{
[ObservableProperty]
private bool isLoading;
public MainPageVM()
{
}
public async void Load()
{
IsLoading = true;
await Task.Delay(8000);
IsLoading = false;
}
}
MauiProgram.cs
using Microsoft.Extensions.Logging;
namespace MauiMRE;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
#if DEBUG
builder.Logging.AddDebug();
#endif
builder.Services.AddTransient<MainPage>();
builder.Services.AddTransient<MainPageVM>();
return builder.Build();
}
}
Upvotes: 0
Views: 76
Reputation: 2078
I did some more experiments and even switched the Radiant gradient to a linear one. Interestingly, the offset property seems really broken. If you add more colours to it, it determines the order of the colours (by ordering them by offset), but that being said, the offsets (0.0, 0.1, 0.2, 0.3) will give the same gradient as (0.0, 0.25, 0.5, 0.75). Also, if you put the gradient along a diagonal (startpoint(0,0) endpoint(1,0)) the gradient doesn't care.
I looked into this example and they used a rectangle not a frame. I exchanged the Frame for a background and it works like a charm.
So the takeaway message is, gradients on a frame behave unexpectedly (at least to me).
Upvotes: 1
Reputation: 21213
Do you want the whole gradient to move? Animate Center.
Center.X, for left-to-right.
As seen in Radial Gradient doc,
Center="0.0,0.0"
places center at upper-left.
Center="1.0,1.0"
places center at lower-right.
————————————
Offset (despite its name) ranges from 0 to 1, as gradient is drawn from center to its radius. Doesn’t make sense for that to be animated from -1 to 1. However, from 0 to 1 should make the Center’s Color expand until the whole circle is that color. If it has NO effect on color, that might be a bug.
Given a second GradientStop at Offset 1.0:
Upvotes: 0