Skip to content

Commit

Permalink
Fix timing on iOS Toolbar (#12363)
Browse files Browse the repository at this point in the history
* Fix timing on iOS Toolbar

* - fix and test titleview measures

* - enable TitleView test for Android

* - account for toolbar changes inside android

* - isolate test to iOS

* - update naming
  • Loading branch information
PureWeen committed Jan 18, 2023
1 parent 4c5dce3 commit d2a0048
Show file tree
Hide file tree
Showing 23 changed files with 748 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ protected virtual void OnPageChanged(Page oldPage, Page newPage)
UpdateTitleView();

if (ShellContext.Shell.Toolbar is ShellToolbar shellToolbar &&
newPage == ShellContext.Shell.CurrentPage)
newPage == ShellContext.Shell.GetCurrentShellPage())
{
shellToolbar.ApplyChanges();
}
Expand All @@ -276,8 +276,8 @@ void OnShellNavigated(object sender, ShellNavigatedEventArgs e)
if (_disposed || Page == null)
return;

if (ShellContext?.Shell?.Toolbar is ShellToolbar shellToolbar &&
Page == ShellContext?.Shell?.CurrentPage)
if (ShellContext?.Shell?.Toolbar is ShellToolbar &&
Page == ShellContext?.Shell?.GetCurrentShellPage())
{
UpdateLeftBarButtonItem();
}
Expand Down Expand Up @@ -579,7 +579,7 @@ void UpdateNavBarHasShadow(Page page)

void OnToolbarPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (_toolbar != null && ShellContext?.Shell?.CurrentPage == Page)
if (_toolbar != null && ShellContext?.Shell?.GetCurrentShellPage() == Page)
{
ApplyToolbarChanges((Toolbar)sender, (Toolbar)_toolbar);
UpdateToolbarIconAccessibilityText(_platformToolbar, ShellContext.Shell);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public Page Page
NSCache _nSCache;
SearchHandlerAppearanceTracker _searchHandlerAppearanceTracker;
IFontManager _fontManager;
bool _isVisiblePage;

BackButtonBehavior BackButtonBehavior { get; set; }
UINavigationItem NavigationItem { get; set; }
Expand All @@ -75,16 +76,13 @@ public ShellPageRendererTracker(IShellContext context)
_nSCache = new NSCache();
_context.Shell.PropertyChanged += HandleShellPropertyChanged;

if (_context.Shell.Toolbar != null)
_context.Shell.Toolbar.PropertyChanged += OnToolbarPropertyChanged;

_fontManager = context.Shell.RequireFontManager();
}

public void OnFlyoutBehaviorChanged(FlyoutBehavior behavior)
{
_flyoutBehavior = behavior;
UpdateToolbarItems();
UpdateToolbarItemsInternal();
}

protected virtual void HandleShellPropertyChanged(object sender, PropertyChangedEventArgs e)
Expand Down Expand Up @@ -142,6 +140,9 @@ protected virtual void UpdateTabBarVisible()

void OnToolbarPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (!ToolbarReady())
return;

if (e.PropertyName == Shell.TitleViewProperty.PropertyName)
{
UpdateTitleView();
Expand All @@ -154,9 +155,21 @@ void OnToolbarPropertyChanged(object sender, PropertyChangedEventArgs e)

protected virtual void UpdateTitle()
{
if (!ToolbarReady())
return;

NavigationItem.Title = _context.Shell.Toolbar.Title;
}


bool ToolbarReady()
{
if (_context.Shell.Toolbar is ShellToolbar st)
return st.CurrentPage == Page;

return _isVisiblePage;
}

void UpdateShellToMyPage()
{
if (Page == null)
Expand All @@ -167,14 +180,15 @@ void UpdateShellToMyPage()
UpdateTitleView();
UpdateTitle();
UpdateTabBarVisible();
UpdateToolbarItems();
UpdateToolbarItemsInternal();
}

protected virtual void OnPageSet(Page oldPage, Page newPage)
{
if (oldPage != null)
{
oldPage.Appearing -= PageAppearing;
oldPage.Disappearing -= PageDisappearing;
oldPage.PropertyChanged -= OnPagePropertyChanged;
oldPage.Loaded -= OnPageLoaded;
((INotifyCollectionChanged)oldPage.ToolbarItems).CollectionChanged -= OnToolbarItemsChanged;
Expand All @@ -183,14 +197,14 @@ protected virtual void OnPageSet(Page oldPage, Page newPage)
if (newPage != null)
{
newPage.Appearing += PageAppearing;
newPage.Disappearing += PageDisappearing;
newPage.PropertyChanged += OnPagePropertyChanged;

if (!newPage.IsLoaded)
newPage.Loaded += OnPageLoaded;

((INotifyCollectionChanged)newPage.ToolbarItems).CollectionChanged += OnToolbarItemsChanged;

UpdateShellToMyPage();
CheckAppeared();

if (oldPage == null)
{
Expand All @@ -215,11 +229,19 @@ protected virtual void OnRendererSet()

protected virtual void UpdateTitleView()
{
if (!ToolbarReady())
return;

var titleView = _context.Shell.Toolbar.TitleView as View;

if (NavigationItem.TitleView is TitleViewContainer tvc &&
tvc.View == titleView)
{
// The MauiContext/handler/other may have changed on the `View`
// This tells the title view container to make sure
// the currently added platformview is still valid and doesn't need
// to be recreated
tvc.UpdatePlatformView();
return;
}

Expand All @@ -231,15 +253,36 @@ protected virtual void UpdateTitleView()
}
else
{
var view = new TitleViewContainer(titleView);
NavigationItem.TitleView = view;
if (titleView.Parent != null)
{
var view = new TitleViewContainer(titleView);
NavigationItem.TitleView = view;
}
else
{
titleView.ParentSet += OnTitleViewParentSet;
}
}
}

void OnTitleViewParentSet(object sender, EventArgs e)
{
((Element)sender).ParentSet -= OnTitleViewParentSet;
UpdateTitleView();
}

internal void UpdateToolbarItemsInternal(bool updateWhenLoaded = true)
{
if (updateWhenLoaded && Page.IsLoaded || !updateWhenLoaded)
UpdateToolbarItems();
}

protected virtual void UpdateToolbarItems()
{
if (NavigationItem == null || !Page.IsLoaded)
if (NavigationItem == null)
{
return;
}

if (NavigationItem.RightBarButtonItems != null)
{
Expand Down Expand Up @@ -302,14 +345,10 @@ void UpdateLeftToolbarItems()
NavigationItem.LeftBarButtonItem =
new UIBarButtonItem(icon, UIBarButtonItemStyle.Plain, (s, e) => LeftBarButtonItemHandler(ViewController, IsRootPage)) { Enabled = enabled };
}
else if (!String.IsNullOrWhiteSpace(text))
{
NavigationItem.LeftBarButtonItem =
new UIBarButtonItem(text, UIBarButtonItemStyle.Plain, (s, e) => LeftBarButtonItemHandler(ViewController, IsRootPage)) { Enabled = enabled };
}
else
{
NavigationItem.LeftBarButtonItem = null;
UpdateBackButtonTitle();
}
if (NavigationItem.LeftBarButtonItem != null)
Expand All @@ -333,6 +372,40 @@ void UpdateLeftToolbarItems()
}
}
});

UpdateBackButtonTitle();
}


void UpdateBackButtonTitle()
{
var behavior = BackButtonBehavior;
var text = behavior.GetPropertyIfSet<string>(BackButtonBehavior.TextOverrideProperty, null);

var navController = ViewController?.NavigationController;

if (navController != null)
{
var viewControllers = ViewController.NavigationController.ViewControllers;
var count = viewControllers.Length;

if (count > 1 && viewControllers[count - 1] == ViewController)
{
var previousNavItem = viewControllers[count - 2].NavigationItem;
if (previousNavItem != null)
{
if (!String.IsNullOrWhiteSpace(text))
{
var barButtonItem = (previousNavItem.BackBarButtonItem ??= new UIBarButtonItem());
barButtonItem.Title = text;
}
else if (previousNavItem.BackBarButtonItem != null)
{
previousNavItem.BackBarButtonItem = null;
}
}
}
}
}

void LeftBarButtonItemHandler(UIViewController controller, bool isRootPage)
Expand Down Expand Up @@ -396,7 +469,7 @@ UIImage DrawHamburger()

void OnToolbarItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
UpdateToolbarItems();
UpdateToolbarItemsInternal();
}

void SetBackButtonBehavior(BackButtonBehavior value)
Expand All @@ -412,7 +485,7 @@ void SetBackButtonBehavior(BackButtonBehavior value)
if (BackButtonBehavior != null)
BackButtonBehavior.PropertyChanged += OnBackButtonBehaviorPropertyChanged;

UpdateToolbarItems();
UpdateToolbarItemsInternal();
}

void OnBackButtonCommandCanExecuteChanged(object sender, EventArgs e)
Expand Down Expand Up @@ -460,7 +533,23 @@ public override CGRect Frame
}
}

public override void LayoutSubviews()
{
if (Height == null || Height == 0)
{
UpdateFrame(Superview);
}

base.LayoutSubviews();
}

public override void WillMoveToSuperview(UIView newSuper)
{
UpdateFrame(newSuper);
base.WillMoveToSuperview(newSuper);
}

void UpdateFrame(UIView newSuper)
{
if (newSuper != null)
{
Expand All @@ -469,8 +558,6 @@ public override void WillMoveToSuperview(UIView newSuper)

Height = newSuper.Bounds.Height;
}

base.WillMoveToSuperview(newSuper);
}

public override CGSize IntrinsicContentSize => UILayoutFittingExpandedSize;
Expand Down Expand Up @@ -713,15 +800,46 @@ void OnPageLoaded(object sender, EventArgs e)
if (sender is Page page)
page.Loaded -= OnPageLoaded;

UpdateToolbarItems();
UpdateToolbarItemsInternal();
CheckAppeared();
}

void PageAppearing(object sender, EventArgs e) =>
SetAppeared();

void PageDisappearing(object sender, EventArgs e) =>
SetDisappeared();

void CheckAppeared()
{
if (_context.Shell.CurrentPage == Page)
SetAppeared();
}

void PageAppearing(object sender, EventArgs e)
void SetAppeared()
{
if (_isVisiblePage)
return;

_isVisiblePage = true;
//UIKIt will try to override our colors when the SearchController is inside the NavigationBar
//Best way was to force them to be set again when page is Appearing / ViewDidLoad
_searchHandlerAppearanceTracker?.UpdateSearchBarColors();
UpdateShellToMyPage();

if (_context.Shell.Toolbar != null)
_context.Shell.Toolbar.PropertyChanged += OnToolbarPropertyChanged;
}

void SetDisappeared()
{
if (!_isVisiblePage)
return;

_isVisiblePage = false;

if (_context.Shell.Toolbar != null)
_context.Shell.Toolbar.PropertyChanged -= OnToolbarPropertyChanged;
}

#endregion SearchHandler
Expand All @@ -743,6 +861,7 @@ protected virtual void Dispose(bool disposing)
_searchHandlerAppearanceTracker?.Dispose();
Page.Loaded -= OnPageLoaded;
Page.Appearing -= PageAppearing;
Page.Disappearing -= PageDisappearing;
Page.PropertyChanged -= OnPagePropertyChanged;
((INotifyCollectionChanged)Page.ToolbarItems).CollectionChanged -= OnToolbarItemsChanged;
((IShellController)_context.Shell).RemoveFlyoutBehaviorObserver(this);
Expand All @@ -754,6 +873,9 @@ protected virtual void Dispose(bool disposing)

if (_context.Shell.Toolbar != null)
_context.Shell.Toolbar.PropertyChanged -= OnToolbarPropertyChanged;

if (NavigationItem?.TitleView is TitleViewContainer tvc)
tvc.Disconnect();
}

_context = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,6 @@ public override void DidShowViewController(UINavigationController navigationCont

public override void WillShowViewController(UINavigationController navigationController, [Transient] UIViewController viewController, bool animated)
{
System.Diagnostics.Debug.Write($"WillShowViewController {viewController.GetHashCode()}");
var element = _self.ElementForViewController(viewController);

bool navBarVisible;
Expand All @@ -716,6 +715,18 @@ public override void WillShowViewController(UINavigationController navigationCon
// handle swipe to dismiss gesture
coordinator.NotifyWhenInteractionChanges(OnInteractionChanged);
}

// Because the back button title needs to be set on the previous VC
// We want to set the BackButtonItem as early as possible so there is no flickering
var currentPage = _self._context?.Shell?.GetCurrentShellPage();
var trackers = _self._trackers;
if (currentPage?.Handler is IPlatformViewHandler pvh &&
pvh.ViewController == viewController &&
trackers.TryGetValue(currentPage, out var tracker) &&
tracker is ShellPageRendererTracker shellRendererTracker)
{
shellRendererTracker.UpdateToolbarItemsInternal(false);
}
}

void OnInteractionChanged(IUIViewControllerTransitionCoordinatorContext context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public virtual void LayoutViews(CGRect bounds, nfloat openPercent, UIView flyout

if (shell.SemanticContentAttribute == UISemanticContentAttribute.ForceRightToLeft)
{
var positionY = shellWidth - openPixels;
flyout.Frame = new CGRect(positionY, 0, flyoutWidth, flyoutHeight);
var positionX = shellWidth - openPixels;
flyout.Frame = new CGRect(positionX, 0, flyoutWidth, flyoutHeight);
}
else
{
Expand Down
Loading

0 comments on commit d2a0048

Please sign in to comment.