Skip to content

Commit

Permalink
feat: TabBarItemExtensions
Browse files Browse the repository at this point in the history
  • Loading branch information
Xiaoy312 committed Sep 6, 2022
1 parent 92daa6a commit 19a5594
Show file tree
Hide file tree
Showing 35 changed files with 897 additions and 85 deletions.
1 change: 1 addition & 0 deletions doc/controls-styles.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The `Uno.Toolkit.UI` library adds the following helper classes:
- [`ControlExtensions`](helpers\control-extensions.md): Provides various attached properties for common controls.
- [`InputExtensions`](helpers\input-extensions.md): Provides various attached properties for _input controls_, such as `TextBox` and `PasswordBox`.
- [`StatusBar`](helpers\StatusBar-extensions.md): Provides two attached properties on `Page` to controls the visual of the status bar on mobile platforms.
- [`TabBarItemExtensions`](helpers\TabBarItem-extensions.md): Provides additional features for `TabBarItem`.

## Control Styles
Control|Style Key|IsDefaultStyle*
Expand Down
29 changes: 29 additions & 0 deletions doc/helpers/TabBarItem-extensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# TabBarItemExtensions Attached Properties
Provides additional features for `TabBarItem`.

## Properties
Property|Type|Description
-|-|-
OnClickBehaviors|TBIOnClickBehavior\*|Backing property for the `TabBarItem` on-click behaviors when already selected.
OnClickBehaviorsTarget|UIElement|Optional. Backing property for the target of OnClickBehaviors.\*

TBIOnClickBehavior\*: Specifies the on-click behaviors of `TabBarItem`:
- `BackNavigation`: Find the first `NavigationView` with back stack to back navigate.
- `ScrollToTop`: Find the first `ListView` or `ScrollViewer` to reset scroll position.
- `Auto`: All of above.

OnClickBehaviorsTarget\*: The content host which the on-click behavior is applied is either the target itself or one of its descendent (via deep first search) suitable for the behavior. When omitted, the parent of `TabBar` will serve as the target.

## Usage
```xml
xmlns:utu="using:Uno.Toolkit.UI"
...

<Grid>
<ListView Grid.Row="0" ... />
<ScrollViewer Grid.Row="0" ... />
<Frame Grid.Row="0" ... />

<TabBar Grid.Row="1">
<utu:TabBarItem ... utu:TabBarItemExtensions.OnClickBehaviors="Auto" />
```
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Uno.Cupertino">
<Version>2.3.0-dev.6</Version>
<Version>2.3.0-dev.12</Version>
</PackageReference>
<PackageReference Include="Uno.Material">
<Version>2.3.0-dev.6</Version>
<Version>2.3.0-dev.12</Version>
</PackageReference>
<PackageReference Include="Uno.UI" Version="4.5.0-dev.453" />
<PackageReference Include="Uno.UI.RemoteControl" Version="4.5.0-dev.453" Condition="'$(Configuration)'=='Debug'" />
<PackageReference Include="Uno.UI" Version="4.5.0-dev.797" />
<PackageReference Include="Uno.UI.RemoteControl" Version="4.5.0-dev.797" Condition="'$(Configuration)'=='Debug'" />
<PackageReference Include="Uno.UniversalImageLoader" Version="1.9.35" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
Expand All @@ -82,7 +82,7 @@
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData">
<Version>2.3.1.1</Version>
</PackageReference>
<PackageReference Include="Uno.UI.Adapter.Microsoft.Extensions.Logging" Version="4.5.0-dev.453" />
<PackageReference Include="Uno.UI.Adapter.Microsoft.Extensions.Logging" Version="4.5.0-dev.797" />
<PackageReference Include="Uno.Core.Extensions.Compatibility" Version="4.0.1" />
<PackageReference Include="Uno.Core.Extensions.Logging.Singleton" Version="4.0.1" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<Page x:Class="Uno.Toolkit.Samples.Content.Controls.TabBarItemExtensionsSamplePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Uno.Toolkit.Samples.Content.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:utu="using:Uno.Toolkit.UI"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">

<!--
TabBarItemExtensionsSamplePage:
tab1: Frame { TabBarItemExtensions_NestedPage1 <-> TabBarItemExtensions_NestedPage2 }
tab2: ListView
tab3: ScrollViewer
-->
<!--
note: This sample must not be placed within a ScrollViewer.
Since ListView or ScrollViewer doesn't work properly when nested under another ScrollViewer.
-->

<Grid x:Name="RootPanel"
Padding="20"
BorderBrush="{ThemeResource SystemControlHighlightBaseMediumRevealBorderBrush}"
BorderThickness="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>

<StackPanel Grid.Row="0"
Margin="0,0,0,20"
Spacing="10">
<TextBlock Style="{StaticResource TitleTextBlockStyle}"
Text="TabBarItemExtensions" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}"
Text="ResetPageOnClick property allows a selected TabBarItem to reset the page content when clicked" />
</StackPanel>

<Frame x:Name="NestedNestedFrame"
Grid.Row="1"
Visibility="{Binding ElementName=TabBarItem_Frame, Path=IsSelected}" />
<Grid Grid.Row="1"
Visibility="{Binding ElementName=TabBarItem_ListView, Path=IsSelected}">
<!-- 20items * 200min-height ~= 4000 -->
<ListView x:Name="LV_SUT"
Grid.Row="1"
Grid.ColumnSpan="2"
ItemsSource="ABCDEFGHIJKLMNOPQRST">
<ListView.ItemTemplate>
<DataTemplate>
<Border MinHeight="200"
Margin="4"
Padding="4"
Background="SkyBlue"
BorderBrush="Azure"
BorderThickness="1"
CornerRadius="8">
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="Black"
Text="{Binding}" />
</Border>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalAlignment"
Value="Stretch" />
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
</ListView>

<StackPanel Margin="16"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Orientation="Vertical"
Spacing="4">
<Button Click="ScrollTop"
Style="{StaticResource IconButtonStyle}"
Tag="{Binding ElementName=LV_SUT}">
<Button.Content>
<PathIcon Data="M12,7L17,12H14V16H10V12H7L12,7M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L5,8.09V15.91L12,19.85L19,15.91V8.09L12,4.15Z"
Foreground="LightGreen"
Tag="arrow-up-bold-hexagon-outline" />
</Button.Content>
</Button>
<Button Click="ScrollBottom"
Style="{StaticResource IconButtonStyle}"
Tag="{Binding ElementName=LV_SUT}">
<Button.Content>
<PathIcon Data="M12,17L7,12H10V8H14V12H17L12,17M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L5,8.09V15.91L12,19.85L19,15.91V8.09L12,4.15Z"
Foreground="LightGreen"
Tag="arrow-down-bold-hexagon-outline" />
</Button.Content>
</Button>
</StackPanel>
</Grid>
<Grid Grid.Row="1"
Visibility="{Binding ElementName=TabBarItem_ScrollViewer, Path=IsSelected}">
<ScrollViewer x:Name="SV_SUT">
<Rectangle Width="100"
Height="4000">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="Red" />
<GradientStop Offset="0.1666" Color="Orange" />
<GradientStop Offset="0.3333" Color="Yellow" />
<GradientStop Offset="0.5" Color="Green" />
<GradientStop Offset="0.6666" Color="Blue" />
<GradientStop Offset="0.8333" Color="Indigo" />
<GradientStop Offset="1" Color="Violet" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</ScrollViewer>

<StackPanel Margin="16"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Orientation="Vertical"
Spacing="4">
<Button Click="ScrollTop"
Style="{StaticResource IconButtonStyle}"
Tag="{Binding ElementName=SV_SUT}">
<Button.Content>
<PathIcon Data="M12,7L17,12H14V16H10V12H7L12,7M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L5,8.09V15.91L12,19.85L19,15.91V8.09L12,4.15Z"
Foreground="LightGreen"
Tag="arrow-up-bold-hexagon-outline" />
</Button.Content>
</Button>
</StackPanel>
</Grid>

<utu:TabBar x:Name="BottomTabBar"
Grid.Row="2"
Style="{StaticResource BottomTabBarStyle}">
<utu:TabBarItem x:Name="TabBarItem_Frame"
utu:TabBarItemExtensions.OnClickBehaviors="Auto"
Content="Frame"
IsSelected="True"
Style="{StaticResource BottomTabBarItemStyle}" />
<utu:TabBarItem x:Name="TabBarItem_ListView"
utu:TabBarItemExtensions.OnClickBehaviors="Auto"
Content="ListView"
Style="{StaticResource BottomTabBarItemStyle}" />
<utu:TabBarItem x:Name="TabBarItem_ScrollViewer"
utu:TabBarItemExtensions.OnClickBehaviors="Auto"
Content="ScrollViewer"
Style="{StaticResource BottomTabBarItemStyle}" />
</utu:TabBar>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using Uno.Toolkit.Samples.Content.NestedSamples;
using Uno.Toolkit.Samples.Entities;
using Uno.Toolkit.UI;

#if IS_WINUI
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
#else
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
#endif

namespace Uno.Toolkit.Samples.Content.Controls
{
[SamplePage(SampleCategory.Behaviors, nameof(TabBarItemExtensions))]
public sealed partial class TabBarItemExtensionsSamplePage : Page
{
public TabBarItemExtensionsSamplePage()
{
this.InitializeComponent();

NestedNestedFrame.Navigate(typeof(TabBarItemExtensions_NestedPage1));
}

private void ScrollTop(object sender, RoutedEventArgs e)
{
if (!(sender is Button button)) return;
if (!(button.Tag is UIElement contentHost)) return;

switch (contentHost)
{
case ListView lv: ScrollableHelper.SmoothScrollTop(lv); break;
case ScrollViewer sv: sv.ChangeView(0, 0, zoomFactor: default, disableAnimation: false); break;

default: throw new InvalidOperationException();
}
}

private void ScrollBottom(object sender, RoutedEventArgs e)
{
if (!(sender is Button button)) return;
if (!(button.Tag is UIElement contentHost)) return;

switch (contentHost)
{
case ListView lv: ScrollableHelper.SmoothScrollBottom(lv); break;

default: throw new InvalidOperationException();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<Page x:Class="Uno.Toolkit.Samples.Content.NestedSamples.TabBarItemExtensions_NestedPage1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Uno.Toolkit.Samples.Content.NestedSamples"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Grid>
<ScrollViewer>
<StackPanel Spacing="50">
<Button Content="Navigate to Page2" Click="GotoNestedPage2" />

<Rectangle Height="4000" Width="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="Red" Offset="0" />
<GradientStop Color="Orange" Offset="0.1666" />
<GradientStop Color="Yellow" Offset="0.3333" />
<GradientStop Color="Green" Offset="0.5" />
<GradientStop Color="Blue" Offset="0.6666" />
<GradientStop Color="Indigo" Offset="0.8333" />
<GradientStop Color="Violet" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</StackPanel>
</ScrollViewer>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace Uno.Toolkit.Samples.Content.NestedSamples
{
public sealed partial class TabBarItemExtensions_NestedPage1 : Page
{
public TabBarItemExtensions_NestedPage1()
{
this.InitializeComponent();
}

private void GotoNestedPage2(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(TabBarItemExtensions_NestedPage2));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Page x:Class="Uno.Toolkit.Samples.Content.NestedSamples.TabBarItemExtensions_NestedPage2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Uno.Toolkit.Samples.Content.NestedSamples"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Grid>
<Button Content="Go Back" Click="GoBack" />
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace Uno.Toolkit.Samples.Content.NestedSamples
{
public sealed partial class TabBarItemExtensions_NestedPage2 : Page
{
public TabBarItemExtensions_NestedPage2()
{
this.InitializeComponent();
}

private void GoBack(object sender, RoutedEventArgs e)
{
Frame.GoBack();
}
}
}
Loading

0 comments on commit 19a5594

Please sign in to comment.