Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix timing on iOS Toolbar #12888

Merged
merged 3 commits into from
Jan 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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