在 Frame 中的 GradientStop 动画没有移动。

huangapple go评论76阅读模式
英文:

GradientStop Animation in Frame is not moving

问题

以下是您要翻译的内容:

"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:

  1. I can change the color of GradientStop
  2. The 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();
    }
}
英文:

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:

  1. I can change the color of GradientStop
  2. The 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

&lt;?xml version = &quot;1.0&quot; encoding = &quot;UTF-8&quot; ?&gt;
&lt;Application xmlns=&quot;http://schemas.microsoft.com/dotnet/2021/maui&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             xmlns:local=&quot;clr-namespace:MauiMRE&quot;
             x:Class=&quot;MauiMRE.App&quot;&gt;
    &lt;Application.Resources&gt;
        &lt;ResourceDictionary&gt;
            &lt;ResourceDictionary.MergedDictionaries&gt;
                &lt;ResourceDictionary Source=&quot;Resources/Styles/Colors.xaml&quot; /&gt;
                &lt;ResourceDictionary Source=&quot;Resources/Styles/Styles.xaml&quot; /&gt;
            &lt;/ResourceDictionary.MergedDictionaries&gt;
        &lt;/ResourceDictionary&gt;
    &lt;/Application.Resources&gt;
&lt;/Application&gt;

App.xaml.cs

namespace MauiMRE;

public partial class App : Application
{ 
    public App()
    {
        InitializeComponent();
        MainPage = new AppShell();
    }
}

AppShell.xaml

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;Shell
    x:Class=&quot;MauiMRE.AppShell&quot;
    xmlns=&quot;http://schemas.microsoft.com/dotnet/2021/maui&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
    xmlns:local=&quot;clr-namespace:MauiMRE&quot;
    Shell.FlyoutBehavior=&quot;Disabled&quot;&gt;

    &lt;ShellContent
        Title=&quot;Home&quot;
        ContentTemplate=&quot;{DataTemplate local:MainPage}&quot;
        Route=&quot;MainPage&quot; /&gt;

&lt;/Shell&gt;

AppShell.xaml.cs

namespace MauiMRE;

public partial class AppShell : Shell
{
    public AppShell()
    {
        InitializeComponent();
    }
}

MainPage.xaml

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;ContentPage xmlns=&quot;http://schemas.microsoft.com/dotnet/2021/maui&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             x:Class=&quot;MauiMRE.MainPage&quot;             
             Title=&quot;Animation Example&quot;&gt;
    &lt;Grid&gt;
        &lt;Grid.RowDefinitions&gt;
            &lt;RowDefinition Height=&quot;Auto&quot;/&gt;
            &lt;RowDefinition Height=&quot;*&quot;/&gt;
        &lt;/Grid.RowDefinitions&gt;
        &lt;Frame IsVisible=&quot;{Binding IsLoading}&quot; MinimumHeightRequest=&quot;40&quot;&gt;
            &lt;Frame.Background&gt;
                &lt;RadialGradientBrush Center=&quot;1.0,1.0&quot;&gt;
                    &lt;GradientStop Color=&quot;Gray&quot; x:Name=&quot;GradientStop&quot;
                    Offset=&quot;0.0&quot; /&gt;
                    &lt;GradientStop Color=&quot;White&quot;
                    Offset=&quot;1.0&quot; /&gt;
                &lt;/RadialGradientBrush&gt;
            &lt;/Frame.Background&gt;
        &lt;/Frame&gt;
    &lt;/Grid&gt;
&lt;/ContentPage&gt;

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 =&gt; { GradientStop.Offset = (float)(1 - Math.Abs(v - 1)); }, 0, 2, Easing.Linear
          );
        GradientStop.Color = Microsoft.Maui.Graphics.Color.FromArgb(&quot;#0000ff&quot;); // color changes
        GradientStop.Offset = 0.3f; // offset doesn&#39;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 = &quot;loadingAnimation&quot;;
            if (mainPageVM.IsLoading)
            {
                loadingAnimation.Commit(this, animationId, 16, 1000, Easing.Linear, (v, c) =&gt; { GradientStop.Offset = 0; }, () =&gt; { 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&lt;App&gt;()
			.ConfigureFonts(fonts =&gt;
			{
				fonts.AddFont(&quot;OpenSans-Regular.ttf&quot;, &quot;OpenSansRegular&quot;);
				fonts.AddFont(&quot;OpenSans-Semibold.ttf&quot;, &quot;OpenSansSemibold&quot;);
			});

#if DEBUG
		builder.Logging.AddDebug();
#endif
        builder.Services.AddTransient&lt;MainPage&gt;();
        builder.Services.AddTransient&lt;MainPageVM&gt;();        
		return builder.Build();
	}
}

答案1

得分: 1

我进行了更多的实验,甚至将辐射渐变切换为线性渐变。有趣的是,偏移属性似乎出现了问题。如果你向其中添加更多的颜色,它会确定颜色的顺序(按偏移排序),但话虽如此,偏移值(0.0, 0.1, 0.2, 0.3)将会产生与(0.0, 0.25, 0.5, 0.75)相同的渐变效果。此外,如果你将渐变放置在对角线上(起点(0,0) 终点(1,0)),渐变就不起作用。

我查看了这个示例,他们使用的是矩形而不是框架。我将框架替换为背景,它运行得非常好。

所以重要的一点是,框架上的渐变行为出乎意料(至少对我来说是这样)。

英文:

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).

答案2

得分: 0

你要整个渐变都移动吗?动画中心。
Center.X,从左到右。

如在径向渐变文档中所示,
Center="0.0,0.0" 将中心放在左上角。
Center="1.0,1.0" 将中心放在右下角。

————————————

偏移量(尽管它的名称是如此)范围从0到1,因为渐变是从中心到其半径绘制的。将其从-1动画到1没有意义。然而,从0到1应该使中心的颜色扩展,直到整个圆都是该颜色。如果它对颜色没有影响,那可能是一个错误。

假设在偏移1.0处有第二个GradientStop:

  • 第一个偏移0.3的GradientStop意味着圆的内部30%是纯色,然后渐变开始。
  • 尝试偏移0.9,会有明显的差异。大部分圆都变成了纯色。(除非您在0处添加第三个GradientStop,以从不同的中心颜色开始。)
英文:

Do you want the whole gradient to move? Animate Center.
Center.X, for left-to-right.

As seen in Radial Gradient doc,
Center=&quot;0.0,0.0&quot; places center at upper-left.
Center=&quot;1.0,1.0&quot; 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:

  • First GradientStop with Offset 0.3 means inner 30% of circle is solid color, then the gradient starts.
  • Try Offset 0.9, for a dramatic difference. Most of the circle becomes solid color. (Unless you add a third GradientStop at 0, to start from a different center color.)

huangapple
  • 本文由 发表于 2023年6月26日 03:24:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76552082.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定