Al John
Al John

Reputation: 900

Is there a workaround for this title bar color bug in .NET MAUI?

Why is the title bar changing colors and is there a workaround for this (presumable) bug?

To verify that this is can be reproduced I've created a new .NET MAUI project. I've added all the code of my fresh project below. It is a bit much but it's really just 3 pages, with buttons with a command that navigates using Shell. Nothing special. Page A and B can both navigate to C. The only difference: A navigates to C using an absolute path /B/C, while B navigates to C directly (push on stack). So under any circumstance, going back from page C always ends up on B.

What happens is this:
B > C > (backto)B = title bar on B stays the same
A > B/C > (backto)B = title bar on B changes background color to dark gray, unintended

The title bar does change back to normal, after navigating away from the page and then going back again. The title bar color change is not permanent throughout the apps lifecycle.

Update
This bug has been reported at the .NET MAUI issues section on Github.

Preview
Using the Pixel 5 Android 13 API 33 emulator: In this example I am using the devices' back button, but the same happens when using an on-page <Button/> in XAML with a command going back to page B instead. It makes no difference.

enter image description here

AppShell

<Shell
    x:Class="TitleBarTest.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:TitleBarTest"
    Shell.FlyoutBehavior="Flyout">
    <FlyoutItem Title="Title Bar Test">
        <ShellContent ContentTemplate="{DataTemplate local:MainPage}"
                      Shell.FlyoutItemIsVisible="True"
                      Shell.TabBarIsVisible="True"
                      Title="Page A" 
                      Route="MainPage"/>
        <ShellContent ContentTemplate="{DataTemplate local:SecondPage}"
                      Shell.FlyoutItemIsVisible="True"
                      Shell.TabBarIsVisible="True"
                      Title="Page B"
                      Route="SecondPage"/>
    </FlyoutItem>
    <ShellContent ContentTemplate="{DataTemplate local:ModalPage}"
                  Shell.FlyoutItemIsVisible="False"
                  Shell.TabBarIsVisible="False"
                  Title="Page C" 
                  Route="ModalPage"/>
</Shell>

Page A

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:TitleBarTest"
             x:DataType="local:MainPageViewModel"
             x:Class="TitleBarTest.MainPage"
             Title="Page A">
    <VerticalStackLayout>
        <Label 
            Text="List of A-items"
            VerticalOptions="Center" 
            HorizontalOptions="Center" />
        <Button
                Command="{Binding GoToModalViaSecondPageCommand}"
                x:Name="CounterBtn"
                Text="Go to C via B"
                HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentPage>

ViewModel A:

public class MainPageViewModel : BaseViewModel
{
    public Command GoToModalViaSecondPageCommand { get; private set; }

    public MainPageViewModel()
    {
        GoToModalViaSecondPageCommand = new Command(GoToModalViaSecondPage);
    }

    public async void GoToModalViaSecondPage()
    {
        await Shell.Current.GoToAsync($"//{nameof(SecondPage)}/{nameof(ModalPage)}");
    }
}

Page B

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:TitleBarTest"
             x:DataType="local:SecondPageViewModel"
             x:Class="TitleBarTest.SecondPage"
             Title="Page B">
    <VerticalStackLayout>
        <Label 
            Text="List of B-items"
            VerticalOptions="Center" 
            HorizontalOptions="Center" />
        <Button
                Command="{Binding GoToModalDirectlyCommand}"
                x:Name="CounterBtn"
                Text="Click me"
                SemanticProperties.Hint="Counts the number of times you click"
                HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentPage>

ViewModel B:

public class SecondPageViewModel : BaseViewModel
{
    public Command GoToModalDirectlyCommand { get; private set; }

    public SecondPageViewModel()
    {
        GoToModalDirectlyCommand = new Command(GoToModalDirectly);
    }

    public async void GoToModalDirectly()
    {
        await Shell.Current.GoToAsync($"{nameof(ModalPage)}");
    }
}

Page C

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:TitleBarTest"
             x:DataType="local:ModalPageViewModel"
             x:Class="TitleBarTest.ModalPage"
             Shell.PresentationMode="ModalAnimated"
             BackgroundColor="#AA000000"
             Title="Page C">
    <StackLayout VerticalOptions="End">
        <Frame BackgroundColor="White"
               CornerRadius="24"
               HeightRequest="256"
               Margin="0,0,0,-24">
            <VerticalStackLayout>
                <Label 
                    Text="Create new B-item"
                    VerticalOptions="Center" 
                    HorizontalOptions="Center" />
            </VerticalStackLayout>
        </Frame>
    </StackLayout>
</ContentPage>

ViewModel C:

public class ModalPageViewModel : BaseViewModel
{
    public Command BackToPageBCommand { get; private set; }

    public ModalPageViewModel()
    {
        BackToPageBCommand = new Command(BackToPageB);
    }

    public async void BackToPageB()
    {
        await Shell.Current.GoToAsync($"//{nameof(SecondPage)}");
    }
}

Styles.xaml
In response to FreakyAlis' comment: The Shell.BackgroundColor is defined in Styles.xaml by default and when I remove this, all title bars have this gray color. It seems like there is a "fall back" color defined somewhere. This is the default:

<Style TargetType="Shell" ApplyToDerivedTypes="True">
    <Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}" />
    ...
    ...
    ...
</Style>

Upvotes: 1

Views: 1087

Answers (1)

Al John
Al John

Reputation: 900

It's not ideal, but popping to root first and then navigating to the desired page, did provide a workaround for this specific occasion.

Instead of only using await Shell.Current.GoToAsync($"//{nameof(DesiredPage)}", true); I would pop to root first like this:

await Shell.Current.Navigation.PopToRootAsync(false);
await Shell.Current.GoToAsync($"//{nameof(DesiredPage)}", true);

And the title bar background color no longer changes for me. I've set the animation parameter to false for PopToRootAsync(false)

Upvotes: 0

Related Questions