Browse Source

Fix: Enable seamless forward and backward transition in VirtualizingCarouselPanel (#14125)

* Update VirtualizingCarouselPanel.cs

Changes the calculation of the "forward" flag for the page transition to enable seamless forward and backward transitions.

* Update VirtualizingCarouselPanel.cs

Added Check for more than 2 items in carousel as there is actually no way to determine the correct transition with only 2 items. If there are only 2 items the transition behaviour is not changed.

* Update VirtualizingCarouselPanelTests.cs

Added Unit Tests for cycling through list forward and backward
pull/14530/head
LuckyGeorge1975 2 years ago
committed by GitHub
parent
commit
56f118d3a9
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 10
      src/Avalonia.Controls/VirtualizingCarouselPanel.cs
  2. 49
      tests/Avalonia.Controls.UnitTests/VirtualizingCarouselPanelTests.cs

10
src/Avalonia.Controls/VirtualizingCarouselPanel.cs

@ -158,7 +158,15 @@ namespace Avalonia.Controls
GetTransition() is { } transition)
{
_transition = new CancellationTokenSource();
transition.Start(_transitionFrom, to, _realizedIndex > _transitionFromIndex, _transition.Token)
var forward = (_realizedIndex > _transitionFromIndex);
if (Items.Count > 2)
{
forward = forward || (_transitionFromIndex == Items.Count - 1 && _realizedIndex == 0);
forward = forward && !(_transitionFromIndex == 0 && _realizedIndex == Items.Count - 1);
}
transition.Start(_transitionFrom, to, forward, _transition.Token)
.ContinueWith(TransitionFinished, TaskScheduler.FromCurrentSynchronizationContext());
}

49
tests/Avalonia.Controls.UnitTests/VirtualizingCarouselPanelTests.cs

@ -147,6 +147,55 @@ namespace Avalonia.Controls.UnitTests
Times.Once);
}
[Fact]
public void Changing_SelectedIndex_transitions_forward_cycle()
{
using var app = Start();
var items = new Control[] { new Button(), new Canvas(), new Label() };
var transition = new Mock<IPageTransition>();
var (target, carousel) = CreateTarget(items, transition.Object);
var cycleindexes = new[] { 1, 2, 0};
for (int cycleIndex = 0; cycleIndex < cycleindexes.Length; cycleIndex++)
{
carousel.SelectedIndex = cycleindexes[cycleIndex];
Layout(target);
var index = cycleIndex;
transition.Verify(x => x.Start(
index > 0 ? items[cycleindexes[index - 1]] : items[0],
items[cycleindexes[index]],
true,
It.IsAny<CancellationToken>()),
Times.Once);
}
}
[Fact]
public void Changing_SelectedIndex_transitions_backward_cycle()
{
using var app = Start();
var items = new Control[] { new Button(), new Canvas(), new Label() };
var transition = new Mock<IPageTransition>();
var (target, carousel) = CreateTarget(items, transition.Object);
var cycleindexes = new[] { 2, 1, 0};
for (int cycleIndex = 0; cycleIndex < cycleindexes.Length; cycleIndex++)
{
carousel.SelectedIndex = cycleindexes[cycleIndex];
Layout(target);
var index = cycleIndex;
transition.Verify(x => x.Start(
index > 0 ? items[cycleindexes[index - 1]] : items[0],
items[cycleindexes[index]],
false,
It.IsAny<CancellationToken>()),
Times.Once);
}
}
[Fact]
public void TransitionFrom_Control_Is_Recycled_When_Transition_Completes()
{

Loading…
Cancel
Save