I have a MAUI app with a Flyout menu.
In the navigation bar beside the burger I show the title and a button (navigating to the user's profile settings).
When I open the app on Android device or Android emulator every second page I enter from the menu, the content inside the Shell.TitleView
disappears.
The order of the selected pages does not matter. That means for example, if I open FirstPage
, ThirdPage
, SecondPage
, FirstPage
in this order, then ThirdPage
and the second opening of FirstPage
has no content in Shell.TitleView
.
The same happens, when I use a HorizontalStackLayout
.
But when I use just a Label
directly in Shell.TitleView
(without a container like a Grid
) then it works fine and on any page the Label
is visible. It also works fine on Windows Machine.
It is also interesting that when I open a second page, the content of the Grid
is displayed correctly for a short moment (matching title of the page), but disappears after about 0.7 seconds.
What is the problem and how it can be solved? Does anyone know of a workaround?
You can find the full example project here: https://mehlhop.com/forum/ProfileApp.7z (113 KB)
A video (kind of screencast) you find here (without download): https://mehlhop.com/forum/20230522_181856_1.mp4
AppShell.xaml:
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:ProfileApp.Views"
x:Class="ProfileApp.AppShell"
FlyoutBehavior="Flyout">
<Shell.TitleView>
<Grid ColumnDefinitions="*,*" BackgroundColor="Red">
<Label Grid.Column="0" x:Name="title" Style="{StaticResource labelPageTitle}"/>
<Button Grid.Column="1" Text="NN" Style="{StaticResource ButtonToProfilePage}" Clicked="ProfileButton_OnClickedAsync"/>
</Grid>
</Shell.TitleView>
<FlyoutItem Title="First" >
<ShellContent ContentTemplate="{DataTemplate views:FirstPage}" />
</FlyoutItem>
<FlyoutItem Title="Second">
<ShellContent ContentTemplate="{DataTemplate views:SecondPage}" />
</FlyoutItem>
<FlyoutItem Title="Third">
<ShellContent ContentTemplate="{DataTemplate views:ThirdPage}" />
</FlyoutItem>
</Shell>
AppShell.xaml.cs:
using ProfileApp.Views;
namespace ProfileApp;
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute(nameof(ProfilePage), typeof(ProfilePage));
}
protected override void OnNavigated(ShellNavigatedEventArgs args)
{
base.OnNavigated(args);
title.Text = Shell.Current.CurrentItem.Title;
}
private async void ProfileButton_OnClickedAsync(object sender, EventArgs e)
{
if (Shell.Current.CurrentPage is ProfilePage) return;
await Shell.Current.GoToAsync(nameof(ProfilePage), true);
title.Text = "Profile Settings";
}
}
MauiProgram.cs (detail):
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
var services = builder.Services;
services.AddTransient<AppShell>();
services.AddTransient<FirstPage>();
services.AddTransient<SecondPage>();
services.AddTransient<ThirdPage>();
services.AddTransient<ProfilePage>();
}
Here is a workaround.
The problem with the disappearing of the TitleView
does not happen, when you reorganise the menu navigation.
Part of AppShell.xaml:
<Shell.FlyoutHeader>
<views:FlyoutHeader />
</Shell.FlyoutHeader>
// defines the start page
<ShellContent FlyoutItemIsVisible="False" ContentTemplate="{DataTemplate views:FirstPage}" Route="FirstPage"/>
<MenuItem ClassId="FirstPage" Text="First" Clicked="MenuItem_OnClicked" />
<MenuItem ClassId="SecondPage" Text="Second" Clicked="MenuItem_OnClicked" />
Part of AppShell.xaml.cs:
public AppShell(/*...*/)
{
//...
Routing.RegisterRoute(nameof(FirstPage), typeof(FirstPage));
Routing.RegisterRoute(nameof(SecondPage), typeof(SecondPage));
Routing.RegisterRoute(nameof(ThirdPage), typeof(ThirdPage));
}
private async void MenuItem_OnClicked(object sender, EventArgs e)
{
var menuItem = sender as MenuItem;
var classId = menuItem?.ClassId;
switch (classId)
{
case null:
return;
case "FirstPage":
await Current.GoToAsync("..", true);
break;
case "SecondPage":
await Current.GoToAsync(nameof(SecondPage), true);
break;
case "ThirdPage":
//...
}
}