Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable TabBar Selection Indicator Customization #477

Merged
merged 9 commits into from
Mar 2, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Binary file added doc/assets/tabbar-selection-red.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/assets/tabbar-selection-slide.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/assets/tabbar-selection-snap.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
349 changes: 216 additions & 133 deletions doc/controls/TabBarAndTabBarItem.md

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions src/Uno.Toolkit.UI/Controls/TabBar/TabBar.Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,50 @@ public Orientation Orientation
DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(TabBar), new PropertyMetadata(Orientation.Horizontal, OnPropertyChanged));
#endregion

#region SelectionIndicatorContent
kazo0 marked this conversation as resolved.
Show resolved Hide resolved
public object? SelectionIndicatorContent
{
get { return (object)GetValue(SelectionIndicatorContentProperty); }
set { SetValue(SelectionIndicatorContentProperty, value); }
}

public static DependencyProperty SelectionIndicatorContentProperty { get; } =
DependencyProperty.Register(nameof(SelectionIndicatorContent), typeof(object), typeof(TabBar), new PropertyMetadata(null, OnPropertyChanged));
#endregion

#region SelectionIndicatorContentTemplate
public DataTemplate SelectionIndicatorContentTemplate
{
get { return (DataTemplate)GetValue(SelectionIndicatorContentTemplateProperty); }
set { SetValue(SelectionIndicatorContentTemplateProperty, value); }
}

public static DependencyProperty SelectionIndicatorContentTemplateProperty { get; } =
DependencyProperty.Register(nameof(SelectionIndicatorContentTemplate), typeof(DataTemplate), typeof(TabBar), new PropertyMetadata(null, OnPropertyChanged));
#endregion

#region SelectionIndicatorPresenterStyle
public Style SelectionIndicatorPresenterStyle
{
get { return (Style)GetValue(SelectionIndicatorPresenterStyleProperty); }
set { SetValue(SelectionIndicatorPresenterStyleProperty, value); }
}

public static DependencyProperty SelectionIndicatorPresenterStyleProperty { get; } =
DependencyProperty.Register(nameof(SelectionIndicatorPresenterStyle), typeof(Style), typeof(TabBar), new PropertyMetadata(null, OnPropertyChanged));
#endregion

#region SelectionIndicatorTransitionMode
public IndicatorTransitionMode SelectionIndicatorTransitionMode
{
get { return (IndicatorTransitionMode)GetValue(SelectionIndicatorTransitionModeProperty); }
set { SetValue(SelectionIndicatorTransitionModeProperty, value); }
}

public static DependencyProperty SelectionIndicatorTransitionModeProperty { get; } =
DependencyProperty.Register(nameof(SelectionIndicatorTransitionMode), typeof(IndicatorTransitionMode), typeof(TabBar), new PropertyMetadata(IndicatorTransitionMode.Snap, OnPropertyChanged));
#endregion

private static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
var owner = (TabBar)sender;
Expand Down
19 changes: 3 additions & 16 deletions src/Uno.Toolkit.UI/Controls/TabBar/TabBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Numerics;
using Uno.Disposables;
using Uno.Extensions.Specialized;
using Windows.Foundation;
Expand Down Expand Up @@ -35,6 +36,7 @@ namespace Uno.Toolkit.UI
public partial class TabBar : ItemsControl
{
private const string TabBarGridName = "TabBarGrid";

private bool _isSynchronizingSelection;
private object? _previouslySelectedItem;
private bool _isLoaded;
Expand All @@ -43,19 +45,9 @@ public partial class TabBar : ItemsControl
public TabBar()
{
DefaultStyleKey = typeof(TabBar);

RegisterPropertyChangedCallback(ItemsSourceProperty, (s, e) => (s as TabBar)?.OnItemsSourceChanged());
Loaded += OnLoaded;
TemplateSettings = new TabBarTemplateSettings();
SizeChanged += OnSizeChanged;
}

private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.PreviousSize.Width != e.NewSize.Width)
{
TemplateSettings.SelectionIndicatorWidth = e.NewSize.Width / Items.Count;
}
}

protected override void OnApplyTemplate()
Expand Down Expand Up @@ -129,13 +121,8 @@ protected override void OnItemsChanged(object e)
}
}
}
SynchronizeInitialSelection();

var itemContainer = GetItemContainers().FirstOrDefault();
if (itemContainer != null)
{
TemplateSettings.SelectionIndicatorWidth = itemContainer.Width;
}
SynchronizeInitialSelection();
}

private void SynchronizeInitialSelection()
Expand Down
95 changes: 92 additions & 3 deletions src/Uno.Toolkit.UI/Controls/TabBar/TabBar.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
<x:Double x:Key="TabBarItemIconWidth">16</x:Double>
<Thickness x:Key="TabBarItemContentMargin">0,0,0,12</Thickness>
<Thickness x:Key="TabBarItemContentOnlyMargin">12,0</Thickness>
<Duration x:Key="TabBarIndicatorAnimationDuration">0:0:0.25</Duration>


<Style x:Key="DefaultTabBarStyle"
TargetType="utu:TabBar">
Expand All @@ -89,15 +91,52 @@
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle"
Value="{StaticResource DefaultTabBarItemStyle}" />
<Setter Property="SelectionIndicatorPresenterStyle"
Value="{StaticResource DefaultTabBarSelectionIndicatorPresenterStyle}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="utu:TabBar">
<Grid x:Name="TabBarGrid"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ItemsPresenter />
BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="OrientationStates">
<VisualState x:Name="Horizontal">
<VisualState.Setters>
<Setter Target="TabBarGrid.Height"
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Height}" />
<Setter Target="SelectionIndicatorPresenter.VerticalContentAlignment"
Value="Stretch" />
<Setter Target="SelectionIndicatorPresenter.HorizontalContentAlignment"
Value="Left" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Vertical">
<VisualState.Setters>
<Setter Target="TabBarGrid.Width"
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}" />
<Setter Target="SelectionIndicatorPresenter.VerticalContentAlignment"
Value="Top" />
<Setter Target="SelectionIndicatorPresenter.HorizontalContentAlignment"
Value="Stretch" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ItemsPresenter x:Name="TabBarItemsPresenter"
Padding="{TemplateBinding Padding}" />
<utu:TabBarSelectionIndicatorPresenter x:Name="SelectionIndicatorPresenter"
Content="{TemplateBinding SelectionIndicatorContent}"
ContentTemplate="{TemplateBinding SelectionIndicatorContentTemplate}"
Style="{TemplateBinding SelectionIndicatorPresenterStyle}"
IndicatorTransitionMode="{TemplateBinding SelectionIndicatorTransitionMode}"
Foreground="{TemplateBinding Foreground}"
Owner="{Binding RelativeSource={RelativeSource TemplatedParent}}"
AutomationProperties.AutomationId="SelectionIndicatorPresenter"
Visibility="Collapsed" />
</Grid>
</ControlTemplate>
</Setter.Value>
Expand Down Expand Up @@ -264,6 +303,52 @@
</Setter>
</Style>

<Style x:Key="DefaultTabBarSelectionIndicatorPresenterStyle"
TargetType="utu:TabBarSelectionIndicatorPresenter">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="utu:TabBarSelectionIndicatorPresenter">
<Grid x:Name="Root">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="IndicatorTransitionStates">
<VisualState x:Name="Horizontal">
<Storyboard x:Name="IndicatorTransitionHorizontalStoryboard">
<DoubleAnimation Storyboard.TargetName="IndicatorTransform"
Storyboard.TargetProperty="TranslateX"
From="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.IndicatorTransitionFrom.X}"
To="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.IndicatorTransitionTo.X}"
Duration="{StaticResource TabBarIndicatorAnimationDuration}" />
</Storyboard>
</VisualState>
<VisualState x:Name="Vertical">
<Storyboard x:Name="IndicatorTransitionVerticalStoryboard">
<DoubleAnimation Storyboard.TargetName="IndicatorTransform"
Storyboard.TargetProperty="TranslateY"
From="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.IndicatorTransitionFrom.Y}"
To="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.IndicatorTransitionTo.Y}"
Duration="{StaticResource TabBarIndicatorAnimationDuration}" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="IndicatorPresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
RenderTransformOrigin=".5,.5"
Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.IndicatorMaxSize.Height}"
Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.IndicatorMaxSize.Width}">
<ContentPresenter.RenderTransform>
<CompositeTransform x:Name="IndicatorTransform" />
</ContentPresenter.RenderTransform>
</ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<!-- TabBar -->
<Style TargetType="utu:TabBar"
BasedOn="{StaticResource DefaultTabBarStyle}" />
Expand All @@ -272,4 +357,8 @@
<Style TargetType="utu:TabBarItem"
BasedOn="{StaticResource DefaultTabBarItemStyle}" />

<!-- TabBarSelectionIndicatorPresenter -->
<Style TargetType="utu:TabBarSelectionIndicatorPresenter"
BasedOn="{StaticResource DefaultTabBarSelectionIndicatorPresenterStyle}" />

</ResourceDictionary>
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ public TabBar Owner
DependencyProperty.Register(nameof(Owner), typeof(TabBar), typeof(TabBarSelectionIndicatorPresenter), new PropertyMetadata(null, OnPropertyChanged));
#endregion

#region TemplateSettings
public TabBarSelectionIndicatorPresenterTemplateSettings TemplateSettings
{
get => (TabBarSelectionIndicatorPresenterTemplateSettings)GetValue(TemplateSettingsProperty);
private set => SetValue(TemplateSettingsProperty, value);
}
public static DependencyProperty TemplateSettingsProperty { get; } =
DependencyProperty.Register(nameof(TemplateSettings), typeof(TabBarSelectionIndicatorPresenterTemplateSettings), typeof(TabBarSelectionIndicatorPresenter), new PropertyMetadata(null));
#endregion

private static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
if (sender is TabBarSelectionIndicatorPresenter owner)
Expand Down
Loading