question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Shell TitleView disappearing on tab change

See original GitHub issue

Description

On iOS Simulator with Shell.FlyoutBehavior=“Flyout” and Tabs, Shell.TitleView is disappearing on tab change.

Steps to Reproduce

  1. Create new .Net MAUI project.

  2. Add couple ContentPages.

  3. Add “AppTitleView” ContentView

  4. Edit AppShell.xaml to set Shell.FlyoutBehavior=“Flyout”

  5. Create couple FlyoutItem with Tab elements.

  6. Add <Shell.TitleView> <shellTitleView:AppTitleView /> </Shell.TitleView> to Content Pages

  7. Run application, switch from “Tab 1” to “Tab 2”

  8. Pages on the “Tab 1” will not show “Shell.TitleView”, but if you named that TitleView control it still accesable from code behind.

  9. Simple project to demostrate the behavior: https://github.com/belmonmi/ShellTitleView

Version with bug

6.0.408

Last version that worked well

Unknown/Other

Affected platforms

iOS, I was not able test on other platforms

Affected platform versions

iOS 15.5

Did you find any workaround?

No

Relevant log output

2022-08-26 12:20:38.115611-0500 ShellTitleView[10063:986797] 
Options:
2022-08-26 12:20:38.115788-0500 ShellTitleView[10063:986797]   --bool-flag (Example)
	type: bool  default: false
2022-08-26 12:20:38.115883-0500 ShellTitleView[10063:986797]   --aot-lazy-assembly-load (Load assemblies referenced by AOT images lazily)
	type: bool  default: false
Resolved pending breakpoint for 'ShellTitleView.Program.Main(System.String[])' to C:\Projects\iNet6\Mobile\Test\Issues\ShellTitleView\ShellTitleView\Platforms\iOS\Program.cs:10 [0x00000].
Resolved pending breakpoint for 'Xamarin.HotReload.HotReloadAgent.BreakpointSendToIde(System.String)' to D:\a\_work\1\s\HotReload\Source\Xamarin.HotReload.Agent\HotReloadAgent.cs:419 [0x00000].
Resolved pending breakpoint for 'Xamarin.HotReload.HotReloadAgent.BreakpointCheckpoint()' to D:\a\_work\1\s\HotReload\Source\Xamarin.HotReload.Agent\HotReloadAgent.cs:414 [0x00000].
2022-08-26 12:20:40.312306-0500 ShellTitleView[10063:986797] SecTaskLoadEntitlements failed error=22 cs_flags=200, pid=10063
2022-08-26 12:20:40.312590-0500 ShellTitleView[10063:986797] SecTaskCopyDebugDescription: ShellTitleView[10063]/0#-1 LF=0
2022-08-26 12:20:40.319471-0500 ShellTitleView[10063:986797] SecTaskLoadEntitlements failed error=22 cs_flags=200, pid=10063
2022-08-26 12:20:40.319731-0500 ShellTitleView[10063:986797] SecTaskCopyDebugDescription: ShellTitleView[10063]/0#-1 LF=0
Thread started:  #2
Thread started:  #3
Thread started:  #4
2022-08-26 12:20:41.484090-0500 ShellTitleView[10063:986797] [TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window. Table view: <_UIMoreListTableView: 0x7fa4daef2c00; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x600002e14330>; layer = <CALayer: 0x600002415140>; contentOffset: {0, 0}; contentSize: {0, 0}; a
djustedContentInset: {0, 0, 0, 0}; dataSource: <UIMoreListController: 0x7fa4d9fa97c0>>
Thread started: .NET Timers #5
Thread started: <Thread Pool> #6
Thread started: .NET ThreadPool Gate #7
Thread started: <Thread Pool> #8
Thread started: <Thread Pool> #9
Thread started: <Thread Pool> #10
Thread started: <Thread Pool> #11
Thread started: <Thread Pool> #12
Thread started: <Thread Pool> #13
Thread started: <Thread Pool> #14
2022-08-26 12:20:45.960535-0500 ShellTitleView[10063:986829] Warning: observer object was not disposed manually with Dispose()
2022-08-26 12:20:45.960790-0500 ShellTitleView[10063:986829] Warning: observer object was not disposed manually with Dispose()

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:2
  • Comments:17 (1 by maintainers)

github_iconTop GitHub Comments

8reactions
vhugogarciacommented, Nov 10, 2022

Hello @belmonmi @borrmann ,

I fixed the issue by using a custom render for AppShell on iOS.

  1. Create a new class DemoMauiApp/Platforms/iOS/Renderers/CustomShellRenderer.cs
using CoreGraphics;
using Microsoft.Maui.Controls.Handlers.Compatibility;
using Microsoft.Maui.Controls.Platform.Compatibility;
using UIKit;

namespace DemoMauiApp.Platforms.iOS.Renderers;

public class CustomShellRenderer : ShellRenderer
{
    protected override IShellPageRendererTracker CreatePageRendererTracker()
    {
        return new CustomShellPageRendererTracker(this);
    }

    protected override IShellNavBarAppearanceTracker CreateNavBarAppearanceTracker()
    {
        return new NoLineAppearanceTracker();
    }
}

public class CustomShellPageRendererTracker : ShellPageRendererTracker
{
    public CustomShellPageRendererTracker(IShellContext context) : base(context) { }

    protected override void UpdateTitleView()
    {
        if (ViewController == null || ViewController.NavigationItem == null)
        {
            return;
        }

        var titleView = Shell.GetTitleView(Page);
        if (titleView == null)
        {
            var view = ViewController.NavigationItem.TitleView;
            ViewController.NavigationItem.TitleView = null;
            view?.Dispose();
        }
        else
        {
            var view = new CustomTitleViewContainer(titleView);
            ViewController.NavigationItem.TitleView = view;
        }
    }
}

public class CustomTitleViewContainer : UIContainerView
{
    public CustomTitleViewContainer(View view) : base(view)
    {
        TranslatesAutoresizingMaskIntoConstraints = false;
    }

    public override CGSize IntrinsicContentSize => UILayoutFittingExpandedSize;
}

public class NoLineAppearanceTracker : IShellNavBarAppearanceTracker
{
    public void Dispose() { }

    public void ResetAppearance(UINavigationController controller) { }

    public void SetAppearance(UINavigationController controller, ShellAppearance appearance)
    {
        var navBar = controller.NavigationBar;
        var navigationBarAppearance = new UINavigationBarAppearance();
        navigationBarAppearance.ConfigureWithOpaqueBackground();
        navigationBarAppearance.ShadowColor = UIColor.Clear;
        navigationBarAppearance.BackgroundColor = UIColor.White; // Set the background color you want on the Shell NavBar
        navBar.ScrollEdgeAppearance = navBar.StandardAppearance = navigationBarAppearance;
    }

    public void SetHasShadow(UINavigationController controller, bool hasShadow) { }

    public void UpdateLayout(UINavigationController controller) { }
}

  1. On the MauiProgram.cs configure the handler:
var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureMauiHandlers(handlers =>
            {
#if IOS
                handlers.AddHandler(typeof(Shell), typeof(DemoMauiApp.Platforms.iOS.Renderers.CustomShellRenderer));
#endif
            });
  1. Rebuild and Run 💯

I hope this helps others as well! Thank you

2reactions
borrmanncommented, Nov 10, 2022

Thank you, works like a charm! Just had to use my inherited class from Shell, in my case AppShell in MauiProgram.cs

Also I would suggest to set the Backgroundcolor using a saved status, so stuff like AppThemeBinding should still work

    public void SetAppearance(UINavigationController controller, ShellAppearance appearance)
    {
        var navBar = controller.NavigationBar;
        var col = navBar.BackgroundColor;
        var navigationBarAppearance = new UINavigationBarAppearance();
        navigationBarAppearance.ConfigureWithOpaqueBackground();
        navigationBarAppearance.ShadowColor = UIColor.Clear;
        navigationBarAppearance.BackgroundColor = col; 
        navBar.ScrollEdgeAppearance = navBar.StandardAppearance = navigationBarAppearance;
    }
Read more comments on GitHub >

github_iconTop Results From Across the Web

Maui: Why the content inside the Shell.TitleView ...
Here is a workaround. The problem with the disappearing of the TitleView does not happen, when you reorganise the menu navigation.
Read more >
Every other tab in Shell doesn't show Shell.TitleView on ...
Hello, I have a pure MAUI app which targets only Android. This are the contents my Shell.xaml file:
Read more >
Maui navigation and TitleView is very confusing
The button shows when the app loads but as soon as I go to another page it disappears and the TitleView seems to...
Read more >
Why does the .net maui title bar disappear on iOS when ...
When you tap in the search box, the virtual keypad appears, but the shell.titleview disappears. (The same thing happens with the standard ...
Read more >
Customize the Title Bar of a MAUI app with these simple steps
In a MAUI Shell app, we can access and control the style of the navigation bar in the root of any ContentPage. In...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found