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 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
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.
347 changes: 213 additions & 134 deletions doc/controls/TabBarAndTabBarItem.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private Shell BuildShell()
AddNavigationItems(nv);

// landing navigation
ShellNavigateTo<SafeAreaSamplePage>(
ShellNavigateTo<TabBarBehaviorSamplePage>(
#if WINDOWS_UWP
// note: on uwp, NavigationView.SelectedItem MUST be set on launch to avoid entering compact-mode
trySynchronizeCurrentItem: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,83 +8,6 @@
xmlns:utu="using:Uno.Toolkit.UI"
mc:Ignorable="d">

<Page.Resources>
<Style x:Key="TabBarWithSlideIndicatorStyle"
TargetType="utu:TabBar">
<Setter Property="IsTabStop"
Value="False" />
<Setter Property="Height"
Value="{StaticResource TabBarHeight}" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<utu:TabBarListPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="utu:TabBar">
<Grid x:Name="TabBarGrid"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Height="{TemplateBinding Height}">
<ItemsPresenter Padding="{TemplateBinding Padding}" />
<utu:TabBarSelectionIndicatorPresenter Owner="{Binding RelativeSource={RelativeSource TemplatedParent}}"
IndicatorTransitionMode="Slide"
Opacity="0">
<Rectangle Fill="Purple"
x:Name="TestingRect"
AutomationProperties.AutomationId="TestingRect"
Height="5"
Width="30" />
</utu:TabBarSelectionIndicatorPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<Style x:Key="TabBarWithSnapIndicatorStyle"
TargetType="utu:TabBar">
<Setter Property="IsTabStop"
Value="False" />
<Setter Property="Height"
Value="{StaticResource TabBarHeight}" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<utu:TabBarListPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="utu:TabBar">
<Grid x:Name="TabBarGrid"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Height="{TemplateBinding Height}">
<ItemsPresenter Padding="{TemplateBinding Padding}" />
<utu:TabBarSelectionIndicatorPresenter Owner="{Binding RelativeSource={RelativeSource TemplatedParent}}"
IndicatorTransitionMode="Snap"
Opacity="0">
<Rectangle Fill="Purple"
x:Name="TestingRect"
AutomationProperties.AutomationId="TestingRect"
Margin="0,0,0,10"
Height="5"
Width="30" />
</utu:TabBarSelectionIndicatorPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<sample:SamplePageLayout IsDesignAgnostic="True">
<sample:SamplePageLayout.DesignAgnosticTemplate>
Expand All @@ -97,11 +20,19 @@
<StackPanel>
<TextBlock Text="TabBar + FlipView with Slide Indicator"
Style="{StaticResource BodyTextBlockStyle}" />
<utu:TabBar Style="{StaticResource TabBarWithSlideIndicatorStyle}"
x:Name="SlideTabBar"
<utu:TabBar x:Name="SlideTabBar"
AutomationProperties.AutomationId="SlideTabBar"
Height="100"
Background="LightBlue"
utu:TabBarSelectorBehavior.Selector="{Binding ElementName=SlideFlipView}"
Background="LightBlue">
SelectionIndicatorTransitionMode="Slide">
<utu:TabBar.SelectionIndicatorContent>
<Rectangle Fill="Purple"
VerticalAlignment="Bottom"
Height="5"
x:Name="SlideTestingRect"
AutomationProperties.AutomationId="SlideTestingRect" />
</utu:TabBar.SelectionIndicatorContent>
<utu:TabBar.Items>
<utu:TabBarItem Content="Tab 1"
AutomationProperties.AutomationId="SlideTab1" />
Expand Down Expand Up @@ -137,6 +68,61 @@
</FlipView>
</StackPanel>
</Border>

<Border Padding="20"
BorderThickness="2"
BorderBrush="{ThemeResource SystemControlHighlightBaseMediumRevealBorderBrush}">
<StackPanel>
<TextBlock Text="TabBar + FlipView with Snap Indicator"
Style="{StaticResource BodyTextBlockStyle}" />
<utu:TabBar x:Name="SnapTabBar"
AutomationProperties.AutomationId="SnapTabBar"
Height="100"
Background="LightBlue"
utu:TabBarSelectorBehavior.Selector="{Binding ElementName=SnapFlipView}"
SelectionIndicatorTransitionMode="Snap">
<utu:TabBar.SelectionIndicatorContent>
<Rectangle Fill="Purple"
x:Name="SnapTestingRect"
AutomationProperties.AutomationId="SnapTestingRect"
VerticalAlignment="Bottom"
Height="5"/>
</utu:TabBar.SelectionIndicatorContent>
<utu:TabBar.Items>
<utu:TabBarItem Content="Tab 1"
AutomationProperties.AutomationId="SnapTab1" />
<utu:TabBarItem Content="Tab 2"
AutomationProperties.AutomationId="SnapTab2" />
<utu:TabBarItem Content="Tab 3"
AutomationProperties.AutomationId="SnapTab3" />
</utu:TabBar.Items>
</utu:TabBar>
<FlipView x:Name="SnapFlipView"
AutomationProperties.AutomationId="SnapFlipView"
Height="100">
<FlipView.Items>
<FlipViewItem AutomationProperties.AutomationId="SnapPage1">
<Grid AutomationProperties.AutomationId="SnapPage1Content"
Background="Blue"
Width="100"
Height="100" />
</FlipViewItem>
<FlipViewItem AutomationProperties.AutomationId="SnapPage2">
<Grid AutomationProperties.AutomationId="SnapPage2Content"
Background="Red"
Width="100"
Height="100" />
</FlipViewItem>
<FlipViewItem AutomationProperties.AutomationId="SnapPage3">
<Grid AutomationProperties.AutomationId="SnapPage3Content"
Background="Green"
Width="100"
Height="100" />
</FlipViewItem>
</FlipView.Items>
</FlipView>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</DataTemplate>
Expand Down
118 changes: 98 additions & 20 deletions src/Uno.Toolkit.UI/Controls/TabBar/TabBar.Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,125 @@ namespace Uno.Toolkit.UI
{
public partial class TabBar
{
#region SelectedItem
public object? SelectedItem
#region DependencyProperty: SelectedItem

public static DependencyProperty SelectedItemProperty { get; } = DependencyProperty.Register(
nameof(SelectedItem),
typeof(object),
typeof(TabBar),
new PropertyMetadata(default(object), OnPropertyChanged));

public object SelectedItem
{
get { return (object)GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
get => (object)GetValue(SelectedItemProperty);
set => SetValue(SelectedItemProperty, value);
}

public static DependencyProperty SelectedItemProperty { get; } =
DependencyProperty.Register(nameof(SelectedItem), typeof(object), typeof(TabBar), new PropertyMetadata(null, OnPropertyChanged));
#endregion
#region DependencyProperty: SelectedIndex

public static DependencyProperty SelectedIndexProperty { get; } = DependencyProperty.Register(
nameof(SelectedIndex),
typeof(int),
typeof(TabBar),
new PropertyMetadata(-1, OnPropertyChanged));

#region SelectedIndex
public int SelectedIndex
{
get { return (int)GetValue(SelectedIndexProperty); }
set { SetValue(SelectedIndexProperty, value); }
get => (int)GetValue(SelectedIndexProperty);
set => SetValue(SelectedIndexProperty, value);
}

public static DependencyProperty SelectedIndexProperty { get; } =
DependencyProperty.Register(nameof(SelectedIndex), typeof(int), typeof(TabBar), new PropertyMetadata(-1, OnPropertyChanged));
#endregion
#region DependencyProperty: TemplateSettings

public static DependencyProperty TemplateSettingsProperty { get; } = DependencyProperty.Register(
nameof(TemplateSettings),
typeof(TabBarTemplateSettings),
typeof(TabBar),
new PropertyMetadata(default(TabBarTemplateSettings)));

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

#endregion
#region DependencyProperty: Orientation

public static DependencyProperty OrientationProperty { get; } = DependencyProperty.Register(
nameof(Orientation),
typeof(Orientation),
typeof(TabBar),
new PropertyMetadata(Orientation.Horizontal, OnPropertyChanged));

#region Orientation
public Orientation Orientation
{
get { return (Orientation)GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
get => (Orientation)GetValue(OrientationProperty);
set => SetValue(OrientationProperty, value);
}

#endregion
#region DependencyProperty: SelectionIndicatorContent

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

public object SelectionIndicatorContent
{
get => (object)GetValue(SelectionIndicatorContentProperty);
set => SetValue(SelectionIndicatorContentProperty, value);
}

#endregion
#region DependencyProperty: SelectionIndicatorContentTemplate

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

public DataTemplate SelectionIndicatorContentTemplate
{
get => (DataTemplate)GetValue(SelectionIndicatorContentTemplateProperty);
set => SetValue(SelectionIndicatorContentTemplateProperty, value);
}

#endregion
#region DependencyProperty: SelectionIndicatorPresenterStyle

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

public Style SelectionIndicatorPresenterStyle
{
get => (Style)GetValue(SelectionIndicatorPresenterStyleProperty);
set => SetValue(SelectionIndicatorPresenterStyleProperty, value);
}

#endregion
#region DependencyProperty: SelectionIndicatorTransitionMode

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

public IndicatorTransitionMode SelectionIndicatorTransitionMode
{
get => (IndicatorTransitionMode)GetValue(SelectionIndicatorTransitionModeProperty);
set => SetValue(SelectionIndicatorTransitionModeProperty, value);
}

public static DependencyProperty OrientationProperty { get; } =
DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(TabBar), new PropertyMetadata(Orientation.Horizontal, OnPropertyChanged));
#endregion

private static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
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 @@ e is IVectorChangedEventArgs iVCE
}
}
}
SynchronizeInitialSelection();

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

private void SynchronizeInitialSelection()
Expand Down
Loading