Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ _updateMenuItemSource is not null &&
}
}

if (DisplayedPage is null)
if (DisplayedPage is null && !_menuSetup)
return;

if (ShellItemController.ShowTabs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ protected virtual void OnItemsCollectionChanged(object sender, NotifyCollectionC
RemoveRenderer(renderer);
}
}

// Recalculate IsInMoreTab for remaining renderers since tab positions shifted after removal.
UpdateIsInMoreTabForRenderers();
}

if (e.NewItems != null && e.NewItems.Count > 0)
Expand Down Expand Up @@ -324,6 +327,22 @@ void SetTabItemsEnabledState()
}
}

void UpdateIsInMoreTabForRenderers()
{
const int maxTabs = 5;
var currentViewControllers = ViewControllers;
if (currentViewControllers == null)
return;

bool willUseMore = currentViewControllers.Length > maxTabs;
for (int i = 0; i < currentViewControllers.Length; i++)
{
var renderer = RendererForViewController(currentViewControllers[i]);
if (renderer != null)
renderer.IsInMoreTab = willUseMore && i >= maxTabs - 1;
}
}

void CreateTabRenderers()
{
if (ShellItem.CurrentItem == null)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
146 changes: 146 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue34343.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
namespace Maui.Controls.Sample.Issues;

[Issue(IssueTracker.Github, 34343, "TabBar displays wrong tabs after first tab becomes invisible", PlatformAffected.Android | PlatformAffected.iOS)]
public class Issue34343 : Shell
{
ContentPage _tab1Page;
public Issue34343()
{
Routing.RegisterRoute("Page51", typeof(Issue34343_Page51));

var tabBar = new TabBar();
var button = new Button
{
Text = "Hide Tab1 and Go to Tab5",
AutomationId = "HideAndNavigateButton",
};

_tab1Page = new ContentPage
{
Title = "Tab1",
Content = new VerticalStackLayout
{
Children = { button }
}
};

button.Clicked += async (s, e) =>
{
// Setting IsVisible = false on the page (as in the issue repro: "this.IsVisible = false")
_tab1Page.IsVisible = false;
await Shell.Current.GoToAsync("///Tab5");
};

var tab1Content = new ShellContent
{
Title = "Tab1",
Route = "Tab1",
Content = _tab1Page
};

var tab1 = new Tab { Title = "Tab1", AutomationId = "Tab1" };
tab1.Items.Add(tab1Content);
tabBar.Items.Add(tab1);

for (int i = 2; i <= 4; i++)
{
int tabNum = i;
var content = new ShellContent
{
Title = $"Tab{tabNum}",
Route = $"Tab{tabNum}",
ContentTemplate = new DataTemplate(() => new ContentPage
{
Title = $"Tab{tabNum}",
Content = new Label
{
Text = $"Tab{tabNum} Content",
AutomationId = $"Tab{tabNum}Content",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}
})
};
var tab = new Tab { Title = $"Tab{tabNum}", AutomationId = $"Tab{tabNum}" };
tab.Items.Add(content);
tabBar.Items.Add(tab);
}

// Tab 5 - has a button to navigate to Page51 (iOS repro: relative sub-page navigation)
var navigateToPage51Button = new Button
{
Text = "Navigate to Page51",
AutomationId = "NavigateToPage51Button",
};
navigateToPage51Button.Clicked += async (s, e) =>
{
await Shell.Current.GoToAsync("Page51");
};

var tab5Page = new ContentPage
{
Title = "Tab5",
Content = new VerticalStackLayout
{
VerticalOptions = LayoutOptions.Center,
Children =
{
new Label
{
Text = "Tab5 Content",
AutomationId = "Tab5Content",
HorizontalOptions = LayoutOptions.Center
},
navigateToPage51Button
}
}
};

var tab5Content = new ShellContent { Title = "Tab5", Route = "Tab5", Content = tab5Page };
var tab5 = new Tab { Title = "Tab5", AutomationId = "Tab5" };
tab5.Items.Add(tab5Content);
tabBar.Items.Add(tab5);

for (int i = 6; i <= 7; i++)
{
int tabNum = i;
var content = new ShellContent
{
Title = $"Tab{tabNum}",
Route = $"Tab{tabNum}",
ContentTemplate = new DataTemplate(() => new ContentPage
{
Title = $"Tab{tabNum}",
Content = new Label
{
Text = $"Tab{tabNum} Content",
AutomationId = $"Tab{tabNum}Content",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}
})
};
var tab = new Tab { Title = $"Tab{tabNum}", AutomationId = $"Tab{tabNum}" };
tab.Items.Add(content);
tabBar.Items.Add(tab);
}

Items.Add(tabBar);
}
}

// Sub-page navigated to from Tab5 (relative route "Page51")
public class Issue34343_Page51 : ContentPage
{
public Issue34343_Page51()
{
Title = "Page51";
Content = new Label
{
Text = "Page51 Content",
AutomationId = "Page51Content",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;

public class Issue34343 : _IssuesUITest
{
public override string Issue => "TabBar displays wrong tabs after first tab becomes invisible";

public Issue34343(TestDevice device) : base(device) { }

#if ANDROID
[Test]
[Category(UITestCategories.Shell)]
public void TabBarShouldDisplayCorrectTabsAfterFirstTabBecomesInvisible()
{
App.WaitForElement("HideAndNavigateButton");
App.Tap("HideAndNavigateButton");
Comment thread
Shalini-Ashokan marked this conversation as resolved.
App.WaitForElement("Tab5Content");
VerifyScreenshot();
}
#endif

#if IOS || MACCATALYST
[Test]
[Category(UITestCategories.Shell)]
public void SubPageNavigationShouldWorkAfterFirstTabBecomesInvisible()
{
App.WaitForElement("HideAndNavigateButton");
App.Tap("HideAndNavigateButton");
App.WaitForElement("Tab5Content");
App.Tap("NavigateToPage51Button");
VerifyScreenshot();
}
#endif
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading