Skip to content

Commit

Permalink
fix: TabBar issues
Browse files Browse the repository at this point in the history
  • Loading branch information
kazo0 committed Mar 15, 2023
1 parent 3edaf9f commit 5ffb6f1
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 15 deletions.
53 changes: 53 additions & 0 deletions src/Uno.Toolkit.RuntimeTests/Tests/TabBarTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,58 @@ public async Task Verify_Indicator_Max_Size()
Assert.AreEqual(expectedWidth, indicator.ActualWidth, delta: 1f);
}

[TestMethod]
[DataRow(Orientation.Horizontal, IndicatorTransitionMode.Snap, DisplayName = "Horizontal Snap")]
[DataRow(Orientation.Horizontal, IndicatorTransitionMode.Slide, DisplayName = "Horizontal Slide")]
[DataRow(Orientation.Vertical, IndicatorTransitionMode.Snap, DisplayName = "Vertical Snap")]
[DataRow(Orientation.Vertical, IndicatorTransitionMode.Slide, DisplayName = "Vertical Slide")]
public async Task Verify_Indicator_Transitions(Orientation orientation, IndicatorTransitionMode transitionMode)
{
const int NumItems = 3;
const double ItemSize = 100d;
var source = Enumerable.Range(0, NumItems).Select(x => new TabBarItem { Content = x }).ToArray();
var indicator = new Border() { Background = new SolidColorBrush(Colors.Red) };
var SUT = new TabBar
{
Orientation = orientation,
ItemsSource = source,
SelectionIndicatorContent = indicator,
SelectionIndicatorTransitionMode = transitionMode,
};

if (orientation == Orientation.Horizontal)
{
SUT.Width = ItemSize * NumItems;
indicator.Height = 5;
}
else
{
SUT.Height = ItemSize * NumItems;
indicator.Width = 5;
}

await UnitTestUIContentHelperEx.SetContentAndWait(SUT);

for (int i = 0; i < NumItems; i++)
{
SUT.SelectedIndex = i;
await UnitTestsUIContentHelper.WaitForIdle();

await UnitTestUIContentHelperEx.WaitFor(() => i * ItemSize == GetTestCoordinate(indicator.TransformToVisual(SUT).TransformPoint(default)), timeoutMS: 2000);

var currentPos = indicator.TransformToVisual(SUT).TransformPoint(default);
Assert.AreEqual(i * ItemSize, GetTestCoordinate(currentPos), delta: 1f);
}

double GetTestCoordinate(Windows.Foundation.Point testPoint)
{
return orientation switch
{
Orientation.Horizontal => testPoint.X,
Orientation.Vertical => testPoint.Y,
_ => throw new ArgumentOutOfRangeException(nameof(orientation))
};
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ private void OnScrolViewerViewChanged(object? sender, ScrollViewerViewChangedEve
// -------------
// 1 2 3 4
var offset =
#if WINDOWS_UWP
#if WINDOWS || WINDOWS_UWP
(scrollViewer.HorizontalOffset - 2) * Selector.ActualWidth;
#else
scrollViewer.HorizontalOffset;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,16 @@ private void OnSelectionOffsetChanged(DependencyObject sender, DependencyPropert
&& _isSelectorPresent
&& IndicatorTransitionMode == IndicatorTransitionMode.Slide)
{
selectionIndicator.RenderTransform = new TranslateTransform
var templateSettings = TemplateSettings;

var destinationPoint = tabBar.Orientation switch
{
X = SelectorExtensions.GetSelectionOffset(tabBar)
Orientation.Horizontal => new Point(SelectorExtensions.GetSelectionOffset(tabBar), templateSettings.IndicatorTransitionFrom.Y),
Orientation.Vertical => new Point(templateSettings.IndicatorTransitionFrom.X, SelectorExtensions.GetSelectionOffset(tabBar)),
_ => throw new ArgumentOutOfRangeException(nameof(tabBar.Orientation))
};

UpdateSelectionIndicatorPosition(destinationPoint);
}
}

Expand All @@ -285,16 +291,19 @@ private void SynchronizeSelection()
_tabBarItemSizeChangedRevoker.Disposable = null;

if (Owner is not { } tabBar ||
tabBar.ContainerFromIndex(tabBar.SelectedIndex) is not TabBarItem newSelectedItem)
tabBar.SelectedIndex == -1)
{
Opacity = 0f;
return;
}

newSelectedItem.SizeChanged += OnSelectedTabBarItemSizeChanged;
_tabBarItemSizeChangedRevoker.Disposable = Disposable.Create(() => newSelectedItem.SizeChanged -= OnSelectedTabBarItemSizeChanged);

Opacity = (Content ?? ContentTemplate) is { } ? 1f : 0f;
if (tabBar.ContainerFromIndex(tabBar.SelectedIndex) is TabBarItem newSelectedItem)
{
newSelectedItem.SizeChanged += OnSelectedTabBarItemSizeChanged;
_tabBarItemSizeChangedRevoker.Disposable = Disposable.Create(() => newSelectedItem.SizeChanged -= OnSelectedTabBarItemSizeChanged);

Opacity = (Content ?? ContentTemplate) is { } ? 1f : 0f;
}
}

private Storyboard? GetStoryboardForCurrentOrientation()
Expand All @@ -313,12 +322,11 @@ private void StopStoryboards()
_verticalStoryboard?.Stop();
}

private void UpdateSelectionIndicatorPosition(TabBarItem? destination = null)
private void UpdateSelectionIndicatorPosition(Point? destination = null)
{
destination ??= Owner?.SelectedItem as TabBarItem;
destination ??= GetRelativePosition(Owner?.SelectedItem as TabBarItem);

if (destination is null ||
Owner is not { } tabBar ||
if (destination == null ||
GetSelectionIndicator() is not { } indicator ||
(indicator.ActualHeight == 0d || indicator.ActualWidth == 0d) ||
GetStoryboardForCurrentOrientation() is not { } storyboard ||
Expand All @@ -329,10 +337,8 @@ private void UpdateSelectionIndicatorPosition(TabBarItem? destination = null)

StopStoryboards();

var nextPosPoint = destination.TransformToVisual(tabBar).TransformPoint(default);

templateSettings.IndicatorTransitionFrom = templateSettings.IndicatorTransitionTo;
templateSettings.IndicatorTransitionTo = nextPosPoint;
templateSettings.IndicatorTransitionTo = destination.Value;

storyboard.BeginTime = TimeSpan.FromMilliseconds(0);

Expand All @@ -343,6 +349,9 @@ private void UpdateSelectionIndicatorPosition(TabBarItem? destination = null)
}
}

private Point? GetRelativePosition(UIElement? element) =>
element?.TransformToVisual(Owner).TransformPoint(default);

private bool IsReady => _isLoaded && _isTemplateApplied;
}
}

0 comments on commit 5ffb6f1

Please sign in to comment.