Xamarin Forms UWP Phone Device TabbedPage - How to underline selected tab and stretch tabs to fill screen?

550 Views Asked by At

I have a cross-platform Xamarin Forms application with a PCL, Android, iOS, and UWP projects. In the UWP project, I am trying to style a tabbed page to where the selected tab is underlined as in the Android project, and the tabs take up the space on the screen regardless of the size of the phone. In the UWP App.xaml I was able to modify the "PivotHeaderItem" style in order to change the color and width of the tabs, but the width is currently hard-coded so the tabs fill the screen only on a 5" emulator and the tabs are not underlined. Below is my code and screenshots. Thanks in advance!

<!--11/28/17 | Style below removes extra unneeded padding on TabbedPage Children Pages-->
<Style TargetType="PivotItem">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Margin" Value="{ThemeResource PivotItemMargin}"/>
<Setter Property="Margin" Value="0,0,0,0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="PivotItem">
            <Grid Background="{TemplateBinding Background}" 
HorizontalAlignment="{TemplateBinding HorizontalAlignment}" 
                                      VerticalAlignment="{TemplateBinding 
VerticalAlignment}">
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="Pivot">
                        <VisualState x:Name="Right"/>
                        <VisualState x:Name="Left"/>
                        <VisualState x:Name="Center"/>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <ContentPresenter HorizontalAlignment="{TemplateBinding 
HorizontalContentAlignment}" 
                                VerticalAlignment="{TemplateBinding 
VerticalContentAlignment}" 
                                ContentTemplate="{TemplateBinding 
ContentTemplate}" 
                                Content="{TemplateBinding Content}" Margin="
{TemplateBinding Padding}"/>
            </Grid>
        </ControlTemplate>
    </Setter.Value>
</Setter>
</Style>

<!--11/28/17 | Style below changes the Background/Foreground of TabbedPage 
Tabs-->
<Style TargetType="PivotHeaderItem">
<Setter Property="FontSize" Value="{ThemeResource 
PivotHeaderItemFontSize}"/>
<Setter Property="FontFamily" Value="{ThemeResource 
PivotHeaderItemFontFamily}"/>
<Setter Property="FontWeight" Value="{ThemeResource 
PivotHeaderItemThemeFontWeight}"/>
<Setter Property="CharacterSpacing" Value="{ThemeResource 
PivotHeaderItemCharacterSpacing}"/>
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="Black"/>
 <!--original value {ThemeResource SystemControlForegroundBaseMediumBrush}--
> 
<Setter Property="Padding" Value="{ThemeResource PivotHeaderItemMargin}"/>
<Setter Property="Height" Value="48"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="PivotHeaderItem">
            <Grid x:Name="Grid" Background="#2196F3" Width="180">
                <!-- original value {TemplateBinding Background}-->
                <Grid.Resources>
                    <Style x:Key="BaseContentPresenterStyle" 
TargetType="ContentPresenter">
                        <Setter Property="FontFamily" Value="Segoe UI"/>
                        <Setter Property="FontWeight" Value="SemiBold"/>
                        <Setter Property="FontSize" Value="15"/>
                        <Setter Property="TextWrapping" Value="Wrap"/>
                        <Setter Property="LineStackingStrategy" 
Value="MaxHeight"/>
                        <Setter Property="TextLineBounds" Value="Full"/>
                        <Setter Property="OpticalMarginAlignment" 
Value="TrimSideBearings"/>
                    </Style>
                    <Style x:Key="BodyContentPresenterStyle" 
TargetType="ContentPresenter" 
BasedOn="{StaticResource BaseContentPresenterStyle}">
                        <Setter Property="FontFamily" Value="{ThemeResource 
PivotHeaderItemFontFamily}"/>
                        <Setter Property="FontWeight" Value="{ThemeResource 
PivotHeaderItemThemeFontWeight}"/>
                        <Setter Property="FontSize" Value="{ThemeResource 
PivotHeaderItemFontSize}"/>
                    </Style>
                </Grid.Resources>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="SelectionStates">
                        <VisualStateGroup.Transitions>
                            <VisualTransition From="Unselected" 
To="UnselectedLocked" GeneratedDuration="0:0:0.33"/>
                            <VisualTransition From="UnselectedLocked" 
To="Unselected" GeneratedDuration="0:0:0.33"/>
                        </VisualStateGroup.Transitions>
                        <VisualState x:Name="Disabled">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="ContentPresenter" 
Storyboard.TargetProperty="Foreground">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="#2196F3"/> <!--| {ThemeResource 
SystemControlDisabledBaseMediumLowBrush} |-->
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Unselected">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="ContentPresenter" 
Storyboard.TargetProperty="Foreground">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="White"/> <!--original value {ThemeResource 
SystemControlHighlightAltBaseHighBrush}-->
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="Grid" Storyboard.TargetProperty="Background">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="#2196F3"/> <!--| #1769aa #C7CECA |-->
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="UnselectedLocked">
                            <Storyboard>
                                <DoubleAnimation 
Storyboard.TargetName="ContentPresenterTranslateTransform" 
Storyboard.TargetProperty="X" Duration="0" To="{ThemeResource 
PivotHeaderItemLockedTranslation}"/>
                                <DoubleAnimation 
Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="
(UIElement.Opacity)" Duration="0" To="0"/>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Selected">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="ContentPresenter" 
Storyboard.TargetProperty="Foreground">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="White"/> <!--original value {ThemeResource 
SystemControlHighlightAltBaseHighBrush}-->
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="Grid" Storyboard.TargetProperty="Background">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="#2196F3"/> <!--| #C7CECA |-->
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="UnselectedPointerOver">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="ContentPresenter" 
Storyboard.TargetProperty="Foreground">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="{ThemeResource SystemControlHighlightAltBaseMediumHighBrush}"/>
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="Grid" Storyboard.TargetProperty="Background">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="{ThemeResource SystemControlHighlightTransparentBrush}"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="SelectedPointerOver">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="ContentPresenter" 
Storyboard.TargetProperty="Foreground">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="{ThemeResource SystemControlHighlightAltBaseMediumHighBrush}"/>
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="Grid" Storyboard.TargetProperty="Background">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="{ThemeResource SystemControlHighlightTransparentBrush}"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="UnselectedPressed">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="ContentPresenter" 
Storyboard.TargetProperty="Foreground">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="White"/> <!--| {ThemeResource 
SystemControlHighlightAltBaseMediumHighBrush} |-->
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="Grid" Storyboard.TargetProperty="Background">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="#2196F3"/> <!--|#1769aa {ThemeResource 
SystemControlHighlightTransparentBrush} |-->
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="SelectedPressed">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="ContentPresenter" 
Storyboard.TargetProperty="Foreground">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="White"/> <!--| {ThemeResource 
SystemControlHighlightAltBaseMediumHighBrush} |-->
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames 
Storyboard.TargetName="Grid" Storyboard.TargetProperty="Background">
                                    <DiscreteObjectKeyFrame KeyTime="0" 
Value="#2196F3"/> <!--| {ThemeResource 
SystemControlHighlightTransparentBrush} |-->
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <ContentPresenter x:Name="ContentPresenter" Content="
{TemplateBinding Content}" ContentTemplate="{TemplateBinding 
ContentTemplate}" Margin="{TemplateBinding Padding}" FontSize="
{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" 
FontWeight="{TemplateBinding FontWeight}" HorizontalAlignment="
{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="
{TemplateBinding VerticalContentAlignment}">
                    <ContentPresenter.RenderTransform>
                        <TranslateTransform 
x:Name="ContentPresenterTranslateTransform"/>
                    </ContentPresenter.RenderTransform>
                </ContentPresenter>
            </Grid>
        </ControlTemplate>
    </Setter.Value>
</Setter>
</Style>

Android Screenshot - Desired Look

UWP Screenshot

1

There are 1 best solutions below

3
On

How to underline selected tab and stretch tabs to fill screen?

For underline the selected tab, you can update the above PivotHeaderItem style to set the Grid border to white and show the bottom BorderThickness when the PivotHeaderItem selected (change the Selected state). Updated style as follows:

<Style TargetType="PivotHeaderItem">
       ...
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="PivotHeaderItem">
                <!-- Here set the Grid Border Brush to white -->
                    <Grid
                        x:Name="Grid"
                        HorizontalAlignment="Stretch"
                        Background="#2196F3"
                        BorderBrush="White">
                        <Grid.Resources>
                            <Style x:Key="BaseContentPresenterStyle" TargetType="ContentPresenter">
                                <Setter Property="FontFamily" Value="Segoe UI" />
                                <Setter Property="FontWeight" Value="SemiBold" />
                                <Setter Property="FontSize" Value="15" />
                                <Setter Property="TextWrapping" Value="Wrap" />
                                <Setter Property="LineStackingStrategy" Value="MaxHeight" />
                                <Setter Property="TextLineBounds" Value="Full" />
                                <Setter Property="OpticalMarginAlignment" Value="TrimSideBearings" />
                            </Style>
                            <Style
                                x:Key="BodyContentPresenterStyle"
                                BasedOn="{StaticResource BaseContentPresenterStyle}"
                                TargetType="ContentPresenter">
                                <Setter Property="FontFamily" Value="{ThemeResource PivotHeaderItemFontFamily}" />
                                <Setter Property="FontWeight" Value="{ThemeResource PivotHeaderItemThemeFontWeight}" />
                                <Setter Property="FontSize" Value="{ThemeResource PivotHeaderItemFontSize}" />
                            </Style>
                        </Grid.Resources>

                        <ContentPresenter
                            x:Name="ContentPresenter"
                            Margin="{TemplateBinding Padding}"
                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                            Content="{TemplateBinding Content}"
                            ContentTemplate="{TemplateBinding ContentTemplate}"
                            FontFamily="{TemplateBinding FontFamily}"
                            FontSize="{TemplateBinding FontSize}"
                            FontWeight="{TemplateBinding FontWeight}">
                            <ContentPresenter.RenderTransform>
                                <TranslateTransform x:Name="ContentPresenterTranslateTransform" />
                            </ContentPresenter.RenderTransform>
                        </ContentPresenter>
                        <VisualStateManager.VisualStateGroups>
                           ...

                                <VisualState x:Name="Selected">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="White" />
                                            <!--
                                                original value {ThemeResource
                                                SystemControlHighlightAltBaseHighBrush}
                                            -->
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Grid" Storyboard.TargetProperty="Background">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="#2196F3" />
                                            <!--  | #C7CECA |  -->
                                        </ObjectAnimationUsingKeyFrames>

                                        <!-- Here set the Grid bottom Border thickness -->
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Grid" Storyboard.TargetProperty="BorderThickness">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,1" /> 
                                        </ObjectAnimationUsingKeyFrames> 
                                    </Storyboard>
                                </VisualState>

                               ...
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

For stretch tabs fill screen, it seems like this cannot be directly set inside style. You may need to dynamic find the inside PivotHeaderItem elements and set the width at run time. For how to find the elements you could reference this thread. For a similar issue in UWP and resolution you may reference this thread.