Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ public SKAnimatedSurfaceView()
Loaded += OnLoaded;
}

protected override void OnPropertyChanged(string? propertyName = null)
{
base.OnPropertyChanged(propertyName);

if (propertyName == nameof(Window))
{
// Restart animation when Window becomes available
// This handles scenarios like CarouselView where views may be created
// before Window is assigned, or Window becomes null and then reassigned
if (Window is not null)
UpdateIsAnimationEnabled();
}
}

/// <summary>
/// Gets or sets a value indicating whether this control will play the animation provided.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,57 @@ static WeakReference Setup(bool animate)
return new WeakReference(view);
}
}

[Fact]
public async Task AnimationStartsWhenWindowBecomesAvailable()
{
// This test verifies the fix for the CarouselView issue where the first
// animation doesn't show because Window is null during initial rendering
var view = new TestAnimatedSurfaceView();
var page = new ContentPage { Content = view };

// Enable animation before Window is assigned
view.IsAnimationEnabled = true;

// Initially, no updates should occur because Window is null
await Task.Delay(50);
Assert.Equal(0, view.UpdateCount);

// Assign the Window - this should trigger animation to start
var window = new Window { Page = page };

// Poll for animation to start with timeout
var started = await PollForConditionAsync(
() => view.UpdateCount > 0,
timeout: TimeSpan.FromSeconds(1));

// Now updates should be occurring
Assert.True(started, "Animation should start after Window is assigned");
}

private static async Task<bool> PollForConditionAsync(Func<bool> condition, TimeSpan timeout)
{
var endTime = DateTime.UtcNow + timeout;
while (DateTime.UtcNow < endTime)
{
if (condition())
return true;
await Task.Delay(10);
}
return false;
}

private class TestAnimatedSurfaceView : SKAnimatedSurfaceView
{
public int UpdateCount { get; private set; }

protected override void Update(TimeSpan deltaTime)
{
base.Update(deltaTime);
// Only count actual animation updates (deltaTime > 0)
// Zero delta time occurs when animation is disabled
if (deltaTime > TimeSpan.Zero)
UpdateCount++;
}
}
}