bugfix(Animation): Fix Infinity animation runasync bug

This commit is contained in:
chinboy
2026-01-12 11:08:46 +08:00
parent 5681ba8466
commit e332012fab
4 changed files with 41 additions and 9 deletions
@@ -0,0 +1,22 @@
using Avalonia.Animation;
namespace AtomUI.Animations;
internal static class AnimationExtensions
{
public static async Task RunInfiniteAsync(this Animation animation, Animatable control,
CancellationToken cancellationToken = default)
{
animation.IterationCount = new IterationCount(1);
try
{
while (!cancellationToken.IsCancellationRequested)
{
await animation.RunAsync(control, cancellationToken);
}
}
catch (TaskCanceledException)
{
}
}
}
@@ -1,4 +1,5 @@
using System.Reactive.Disposables;
using AtomUI.Animations;
using AtomUI.Controls;
using AtomUI.Data;
using Avalonia;
@@ -7,6 +8,7 @@ using Avalonia.Animation.Easings;
using Avalonia.Controls.Primitives;
using Avalonia.Media;
using Avalonia.Styling;
using Avalonia.Threading;
using Avalonia.VisualTree;
namespace AtomUI.Desktop.Controls;
@@ -150,11 +152,12 @@ public abstract class AbstractSkeleton : TemplatedControl
protected void StartActiveAnimation()
{
_cancellationTokenSource?.Cancel();
_cancellationTokenSource = new CancellationTokenSource();
if (_animation != null)
{
_cancellationTokenSource?.Cancel();
_cancellationTokenSource = new CancellationTokenSource();
_animation?.RunAsync(this, _cancellationTokenSource.Token);
Dispatcher.UIThread.InvokeAsync(async () =>
await _animation.RunInfiniteAsync(this, _cancellationTokenSource.Token));
}
}
@@ -179,7 +182,6 @@ public abstract class AbstractSkeleton : TemplatedControl
_cancellationTokenSource?.Cancel();
_animation = new Animation
{
IterationCount = IterationCount.Infinite,
Easing = MotionEasingCurve ?? new CubicEaseOut(),
Duration = MotionDuration,
Children =
@@ -1,4 +1,5 @@
using AtomUI.Controls;
using AtomUI.Animations;
using AtomUI.Controls;
using AtomUI.Desktop.Controls.DesignTokens;
using AtomUI.Desktop.Controls.Themes;
using AtomUI.Theme;
@@ -15,6 +16,7 @@ using Avalonia.Media;
using Avalonia.Media.Transformation;
using Avalonia.Metadata;
using Avalonia.Styling;
using Avalonia.Threading;
namespace AtomUI.Desktop.Controls;
@@ -139,7 +141,13 @@ public class SpinIndicator : TemplatedControl,
BuildIndicatorAnimation();
_cancellationTokenSource?.Cancel();
_cancellationTokenSource = new CancellationTokenSource();
_animation?.RunAsync(this, _cancellationTokenSource.Token);
if (_animation != null)
{
Dispatcher.UIThread.InvokeAsync(async () =>
{
await _animation.RunInfiniteAsync(this, _cancellationTokenSource.Token);
});
}
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
@@ -182,7 +190,6 @@ public class SpinIndicator : TemplatedControl,
_cancellationTokenSource?.Cancel();
_animation = new Animation
{
IterationCount = IterationCount.Infinite,
Easing = MotionEasingCurve ?? new LinearEasing(),
Duration = MotionDuration,
Children =
@@ -1,4 +1,5 @@
using System.Reactive.Disposables;
using AtomUI.Animations;
using AtomUI.Controls;
using AtomUI.Desktop.Controls.DesignTokens;
using AtomUI.Data;
@@ -12,6 +13,7 @@ using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.Styling;
using Avalonia.Threading;
using Avalonia.VisualTree;
namespace AtomUI.Desktop.Controls;
@@ -170,7 +172,6 @@ internal class SwitchKnob : Control
_bindingDisposable?.Dispose();
_bindingDisposable = BindUtils.RelayBind(this, LoadingAnimationDurationProperty, loadingAnimation, Animation.DurationProperty);
loadingAnimation.Duration = LoadingAnimationDuration;
loadingAnimation.IterationCount = IterationCount.Infinite;
loadingAnimation.Easing = new LinearEasing();
loadingAnimation.Children.Add(new KeyFrame
{
@@ -197,7 +198,7 @@ internal class SwitchKnob : Control
KeyTime = LoadingAnimationDuration
});
_cancellationTokenSource = new CancellationTokenSource();
loadingAnimation.RunAsync(this, _cancellationTokenSource!.Token);
Dispatcher.UIThread.InvokeAsync(async () => await loadingAnimation.RunInfiniteAsync(this, _cancellationTokenSource.Token));
}
public void NotifyStopLoading()