File: Compatibility\Handlers\iOS\MauiNavigationBar.cs
Web Access
Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls)
using System;
using CoreGraphics;
using ObjCRuntime;
using UIKit;
using RectangleF = CoreGraphics.CGRect;
 
namespace Microsoft.Maui.Controls.Handlers.Compatibility;
 
/// <summary>
/// This class is used to adjust the navigation bar for the title bar on Mac Catalyst when a new titlebar is added or removed.
/// </summary>
internal class MauiNavigationBar : UINavigationBar
{
    internal bool TitleBarNeedsRefresh { get; set; }
    nfloat? _originalSafeAreaConstant = null;
 
    [Internals.Preserve(Conditional = true)]
    public MauiNavigationBar() : base()
    {
    }
 
    [Internals.Preserve(Conditional = true)]
    public MauiNavigationBar(Foundation.NSCoder coder) : base(coder)
    {
    }
 
    [Internals.Preserve(Conditional = true)]
    protected MauiNavigationBar(Foundation.NSObjectFlag t) : base(t)
    {
    }
 
    [Internals.Preserve(Conditional = true)]
    protected internal MauiNavigationBar(IntPtr handle) : base(handle)
    {
    }
 
    [Internals.Preserve(Conditional = true)]
    public MauiNavigationBar(RectangleF frame) : base(frame)
    {
    }
 
    protected internal MauiNavigationBar(NativeHandle handle) : base(handle)
    {
    }
 
    public override void SafeAreaInsetsDidChange()
    {
        if (_originalSafeAreaConstant is null)
        {
            _originalSafeAreaConstant = SafeAreaInsets.Top;
        }
 
        base.SafeAreaInsetsDidChange();
#if MACCATALYST
        AdjustForTitleBar();
#endif
    }
 
#if MACCATALYST
    void AdjustForTitleBar()
    {
        var controller = Window?.RootViewController as WindowViewController;
 
        if (controller?.HasCustomTitleBar == true && _originalSafeAreaConstant is nfloat originalSafeAreaConstant)
        {
            var currentSafeAreaTop = SafeAreaInsets.Top;
            var titleBarHeight = controller._contentWrapperTopConstraint?.Constant ?? 0;
 
            if (currentSafeAreaTop > 0 && Frame.Y < originalSafeAreaConstant && titleBarHeight == 0)
            {
                controller.IsFirstLayout = false;
                Frame = new CGRect(Frame.X, originalSafeAreaConstant, Frame.Width, Frame.Height);
                TitleBarNeedsRefresh = true;
            }
            else if (controller.IsFirstLayout)
            {
                controller.IsFirstLayout = false;
                Frame = new CGRect(Frame.X, Math.Max(originalSafeAreaConstant - titleBarHeight, 0), Frame.Width, Frame.Height);
                TitleBarNeedsRefresh = true;
            }
        }
    }
#endif
 
    internal void RefreshIfNeeded()
    {
        if (TitleBarNeedsRefresh)
		{
			Superview?.SetNeedsLayout();
			TitleBarNeedsRefresh = false;
		}
    }
}