Fixed Shell TitleView disappears when switching between tabs on Android #33469
Fixed Shell TitleView disappears when switching between tabs on Android #33469kubaflo merged 11 commits intodotnet:inflight/currentfrom
Conversation
|
Hey there @@KarthikRajaKalaimani! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
There was a problem hiding this comment.
Pull request overview
This PR fixes a regression in .NET MAUI 9.0.30 where Shell TitleView disappears when switching between tabs on Android. The fix ensures that when a fragment becomes visible after being hidden (during tab switching), the TitleView is properly refreshed.
Changes:
- Added
OnHiddenChangedoverride inShellSectionRendererto update TitleView when fragment becomes visible - Stored
Toolbarreference as field to enable TitleView updates during fragment visibility changes - Added UI test to verify TitleView persists when switching tabs
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
ShellSectionRenderer.cs |
Stores Toolbar reference as _shellToolbar field and overrides OnHiddenChanged to update TitleView when fragment becomes visible after tab switch |
PublicAPI.Unshipped.txt |
Documents the new public API method OnHiddenChanged override for Android |
Issue33304.cs (HostApp) |
Implements test page with Shell containing multiple tabs and a TitleView to reproduce the issue |
Issue33304.cs (Tests) |
Adds automated UI test that switches tabs and verifies TitleView persists |
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs
Outdated
Show resolved
Hide resolved
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs
Outdated
Show resolved
Hide resolved
🤖 AI Summary📊 Expand Full Review —
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix (prior) | Post delayed UpdateTitleView() in ShellToolbarTracker.OnShellNavigated() when ` FAIL |
ShellToolbarTracker.cs |
Navigation event fires before fragment visibility change | ShellSectionChanged` |
| PR | PR #33469 | Override OnHiddenChanged to update TitleView when fragment becomes PENDING (Gate) |
ShellSectionRenderer.cs (+17), PublicAPI.Unshipped.txt (+1) |
Original PR, all feedback addressed | visible |
Issue: #33304 - [Android] TitleView defined in Shell is lost when changing tabs
PR: #33469 - Fixed Shell TitleView disappears when switching between tabs on Android
Platforms Affected: Android
Files Changed: 2 implementation, 2 test
Key Findings
- The linked issue is an Android-only regression introduced after MAUI 9.0.22 and reproducible from 9.0.30 onward; the original repro specifically notes the TitleView disappears on the second tab and reappears on the third.
- The PR changes one Android Shell compatibility renderer plus its Android PublicAPI entry, and adds a HostApp + shared UI test pair for
Issue33304. - Prior review feedback focused on null-safety,
nameof(Toolbar.TitleView), and clearing_shellToolbarinDestroy(); those comments are resolved in the current diff. - A prior agent review exists in PR comments and previously recommended approval on an earlier commit after reporting Gate pass and multiple alternative fixes.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #33469 | Override OnHiddenChanged to refresh Toolbar.TitleView when a hidden Android Shell section becomes visible again |
⏳ PENDING (Gate) | src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs, src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt |
Original PR; UI test coverage added via Issue33304 HostApp + shared test files |
🚦 Gate — Test Verification
📝 Review Session — Set _shellToolbar to null on Destroy method · 9eeed4d
Result: ✅ PASSED
Platform: android
Mode: Full Verification (RequireFullVerification: true)
- Tests FAIL without fix ✅
- Tests PASS with fix ✅
Test: Issue33304Test
Fix Files Verified:
- src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs
- src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt
Gate Result: ✅ PASSED
Platform: android
Mode: Full Verification
- Tests FAIL without fix: ✅
- Tests PASS with fix: ✅
Evidence: pwsh .github/skills/verify-tests-fail-without-fix/scripts/verify-tests-fail.ps1 -Platform android -TestFilter "Issue33304" -RequireFullVerification
🔧 Fix — Analysis & Comparison
📝 Review Session — Set _shellToolbar to null on Destroy method · 9eeed4d
Result: ✅ PASSED
Platform: android
Mode: Full Verification (RequireFullVerification: true)
- Tests FAIL without fix ✅
- Tests PASS with fix ✅
Test: Issue33304Test
Fix Files Verified:
- src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs
- src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix (claude-opus-4.6) | Refresh TitleView from ShellItemRendererBase.HandleFragmentUpdate after ShellSectionChanged by forcing pending transactions and calling internal refresh helpers |
✅ PASS | 3 files | Parent-driven lifecycle alternative; broader plumbing than PR fix |
| 2 | try-fix (claude-sonnet-4.6) | Post a refresh callback from ShellItemRendererBase after fragment commit and call an internal ShellSectionRenderer.RefreshTitleView() helper |
✅ PASS | 2 files | Relies on concrete ShellSectionRenderer cast and looper ordering |
| 3 | try-fix (gpt-5.3-codex) | Rebind the toolbar tracker during ShellSectionChanged by resetting Page through a new ShellSectionRenderer.RefreshToolbarForCurrentItem() helper |
✅ PASS | 2 files | Uses tracker/page rebinding rather than direct handler update |
| 4 | try-fix (gemini-3-pro-preview) | In OnHiddenChanged, toggle _toolbarTracker.Page null→current page to force the tracker to re-run UpdateTitleView() |
✅ PASS | 2 files | Reuses tracker abstraction but still depends on the same lifecycle callback as PR |
| 5 | try-fix (claude-opus-4.6 R2) | Same-page tracker refresh variants entirely inside ShellToolbarTracker |
❌ FAIL | 1 file | Repeated UpdateValue(nameof(Toolbar.TitleView)) remained effectively idempotent |
| 6 | try-fix (claude-sonnet-4.6 R2) | Native Toolbar.Android.Container reclaim logic that re-applies TitleView when its child was stolen during tab switches |
✅ PASS | 1 file | Deeper native-view fix outside Shell-specific code |
| 7 | try-fix (gpt-5.3-codex R2) | Toolbar-local visibility/self-heal changes inside Toolbar.UpdateTitleView() |
❌ FAIL | 1 file | Re-showing native view state alone did not restore TitleView after fragment reuse |
| PR | PR #33469 | Override OnHiddenChanged in ShellSectionRenderer and call _shellToolbar.Handler.UpdateValue(nameof(Toolbar.TitleView)) when visible again |
✅ PASS (Gate) | 2 files | Original PR |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 1 | Yes | Tracker-only same-page refresh inside ShellToolbarTracker |
| claude-sonnet-4.6 | 1 | Yes | Native toolbar re-attach / reclaim on Android view lifecycle |
| gpt-5.3-codex | 1 | Yes | Self-healing visibility in Toolbar.UpdateTitleView() |
| gemini-3-pro-preview | 1 | No | NO NEW IDEAS |
| claude-opus-4.6 | 2 | No | NO NEW IDEAS |
| claude-sonnet-4.6 | 2 | No | NO NEW IDEAS |
| gpt-5.3-codex | 2 | No | NO NEW IDEAS |
| gemini-3-pro-preview | 2 | No | NO NEW IDEAS |
Exhausted: Yes
Selected Fix: PR's fix — It is the best balance of correctness and scope: Android-specific, direct, minimal, and validated by Gate. The other passing candidates either add broader Shell coordination, depend on concrete renderer casts, or change generic toolbar/container behavior beyond the reported regression.
📋 Report — Final Recommendation
📝 Review Session — Set _shellToolbar to null on Destroy method · 9eeed4d
✅ Final Recommendation: APPROVE
Summary
PR #33469 fixes a regression (introduced in MAUI 9.0.30) where Shell.TitleView disappears when switching between tabs on Android. The fix is minimal, well-targeted, and all reviewer feedback has been addressed.
Root Cause
When switching Shell tabs on Android, fragments are reused via HideEx()/ShowEx() calls in ShellItemRendererBase.HandleFragmentUpdate (lines 235-242). When a fragment becomes visible again, OnHiddenChanged(false) fires, but the Toolbar.TitleView handler update was never triggered — leaving the TitleView invisible. This is an Android-specific issue tied to fragment lifecycle.
Fix Quality
The PR overrides OnHiddenChanged in ShellSectionRenderer to explicitly update the TitleView handler when the fragment becomes visible:
public override void OnHiddenChanged(bool hidden)
{
base.OnHiddenChanged(hidden);
if (!hidden && _shellToolbar?.Handler != null)
{
_shellToolbar.Handler.UpdateValue(nameof(Toolbar.TitleView));
}
}Why this is the optimal fix:
- Minimal footprint: 11 lines of logic in 1 Android-specific file
- Correct lifecycle timing:
OnHiddenChangedfires at the exact moment fragment visibility changes - Directly updates the broken property (
TitleView) with proper null safety andnameof()type safety - 5 alternative approaches (try-fix) were explored — all passing but with higher complexity or risk
- 1 alternative (removing guard in ShellToolbarTracker) confirmed ❌ — guards are necessary
Try-Fix Summary
6 alternatives explored:
- ✅ Interface method on IShellObservableFragment (more complex, adds public API)
- ✅ ShellSection.Appearing event subscription (cross-platform event for Android-specific issue)
- ✅ Detach/Attach instead of Hide/Show (higher regression risk)
- ✅ RefreshToolbarForSection() via page null→current (more indirect)
- ✅ OnHiddenChanged with tracker page reset (variant of PR's approach)
- ❌ Remove guard in ShellToolbarTracker.UpdateTitleView() (guards are necessary)
Selected Fix: PR's fix — simplest, most direct, lowest risk
PR Metadata Review
Title: Minor update recommended
- Current:
Fixed Shell TitleView disappears when switching between tabs on Android(trailing space) - Suggested:
[Android] Shell: Fix TitleView disappearing when switching between tabs
Description: Good — has NOTE block, root cause, fix description, tested platforms, issue link. Missing "What NOT to Do" section for future agents (guard removal approach doesn't work).
Gate Result
✅ PASSED on Android:
- Tests FAIL without fix (bug reproduced)
- Tests PASS with fix
Minor Suggestions (Non-blocking)
- Fix trailing space in title, add
[Android]prefix - Add "What NOT to Do" to description: Don't remove
GetCurrentShellPage() == Pageguard inShellToolbarTracker— guards are necessary - Consider testing Settings tab in test (matches original 3-tab repro) — current test is sufficient
✅ Final Recommendation: APPROVE
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | ✅ COMPLETE | Android-only regression from issue #33304; prior review feedback resolved |
| Gate | ✅ PASSED | Android full verification: tests fail without fix and pass with fix |
| Try-Fix | ✅ COMPLETE | 7 candidates evaluated, 5 passing; PR fix selected after exhaustion round |
| Report | ✅ COMPLETE |
Summary
PR #33469 fixes the Android Shell regression where Shell.TitleView disappears when switching tabs. The added UI test was validated in both directions on Android, and the fix remained the best option after evaluating seven alternative approaches.
A local review-branch quirk surfaced unrelated squashed files that were not part of the GitHub PR diff, so the try-fix comparison was intentionally constrained to the actual Android Shell issue scope from GitHub metadata and the verified Issue33304 test path.
Root Cause
For ShellNavigationSource.ShellSectionChanged, Android reuses existing fragments by hiding and showing them. When a previously hidden ShellSectionRenderer becomes visible again, the toolbar TitleView is not refreshed automatically, so the shared TitleView no longer appears on the visible tab.
Fix Quality
The PR fixes the problem in the narrowest correct place: ShellSectionRenderer.OnHiddenChanged(false). That hook fires exactly when the previously hidden fragment becomes visible again, and the fix directly re-applies Toolbar.TitleView with proper null-safety.
Compared with the passing alternatives, the PR avoids extra Shell coordination code, avoids concrete renderer casts in parent orchestration, and avoids changing generic toolbar/container behavior for an Android Shell-specific regression. That makes it the lowest-risk and clearest fix of the set.
📋 Expand PR Finalization Review
PR #33469 Finalization Review
Title
Current: Fixed Shell TitleView disappears when switching between tabs on Android
Recommended: [Android] Shell: Refresh TitleView when switching back to a tab
Why:
- Uses the repo's preferred searchable format: platform + component + behavior.
- Drops the trailing space and the generic
Fixedwording. - Describes the implemented behavior instead of restating the issue in prose.
Description
✅ Good foundation, but it should be tightened rather than replaced.
Keep:
- The required NOTE block is already present.
- The current root-cause explanation is directionally correct.
- The description already points at the fragment hide/show behavior that causes the regression.
Recommended edits:
- Fix wording/typos:
reuse fragmentsorreuses fragmentsinstead of awkward wordingshellToolbarinstead ofshellToobar
- Make the implementation description more explicit:
- Mention that
ShellSectionRenderer.OnHiddenChanged(bool hidden)now refreshesnameof(Toolbar.TitleView)when an existing tab fragment becomes visible again. - Mention that the renderer now keeps a
Toolbarreference (_shellToolbar) so the TitleView handler can be updated on re-show.
- Mention that
- Mention the added regression coverage:
src/Controls/tests/TestCases.HostApp/Issues/Issue33304.cssrc/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33304.cs
- Fix the platform testing section:
- This is an Android-specific fix and Android-specific UI regression test. Do not mark Windows/iOS/Mac as tested unless they were actually validated.
- Normalize the issue link formatting to
Fixes #33304.
Suggested revised Description of Change:
When Shell switches tabs on Android, it can reuse existing fragments by hiding and showing them instead of recreating them. In that path, the TitleView handler is not automatically refreshed when a previously hidden tab becomes visible again, so the TitleView disappears.
This change stores the Shell toolbar instance on
ShellSectionRendererand refreshesnameof(Toolbar.TitleView)fromOnHiddenChanged(bool hidden)when the fragment becomes visible again. A UI regression test was also added to verify that the TitleView remains visible after switching away from and back to a tab.
Code Review Findings
✅ Looks good
- The implementation is small and targeted to the Android Shell fragment lifecycle path that matches the reported regression.
- Prior review concerns appear to be addressed:
_shellToolbaris now nulled inDestroy().OnHiddenChangedguards against a missing handler.nameof(Toolbar.TitleView)is used instead of a magic string.
- The PR includes a regression UI test, not just the renderer fix.
PublicAPI.Unshipped.txtwas updated for the new override, which is consistent with repo requirements.
🔴 Critical issues
- None found in the changed files.
🟡 Suggestions
- The description should explicitly mention the new UI regression test and avoid claiming non-Android platform validation unless that actually happened.
- Consider adding an
_disposedguard at the start ofOnHiddenChanged(bool hidden). The null check on_shellToolbarhelps, but other handlers in this renderer already use_disposeddefensively around fragment lifecycle timing. - Consider extending the UI test to visit the third tab as well, since the repro description mentions the TitleView disappearing on one tab transition pattern across multiple tabs. The current test still exercises the core hide/show path, but broader navigation coverage would better match the issue narrative.
Informational notes
- Current PR status is still not fully green: GitHub check runs show
maui-prandBuild Analysisfailing at the time of review. - The PR's current mergeable state is
blockedin GitHub metadata. This review did not investigate the failing checks or merge block reason.
Overall assessment
The code changes themselves look mergeable from a code-review perspective. The main follow-up is PR metadata cleanup: update the title to the standard format, tighten the description so it precisely matches the implementation, and correct the platform testing claims.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs
Show resolved
Hide resolved
|
/rebase |
2f1b346 to
9eeed4d
Compare
I have renamed the test method as suggested, changing it from Issue33304Test to TitleViewPersistsAfterSwitchingTabs. I also verified the other Shell and page toolbar properties. The issue does not occur with those properties, as they are independent of Shell.TitleView. Therefore, they do not need to be updated in the OnHiddenChanged method. Regarding the missing AutomationId for the Settings tab label, it is not required to set an AutomationId for that tab. |
|
|
1c2f4b5 to
4114040
Compare
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 33469Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 33469" |
I have rebased the branch and resolved the conflicts |
|
/azp run maui-pr-uitests , maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
0bba31b to
627b389
Compare
…id (#33469) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Issue Details: Shell TitleView disappears when switching between tabs on Android (regression from MAUI 9.0.30). ### Root Cause: When switching tabs, we reuses fragments by hiding/showing them if the ShellNavigationSource is ShellSectionChanged in ShellItemRendererBase class(line number 235 to 242). When a fragment becomes visible again, the TitleView handler update isn't automatically triggered, leaving the TitleView invisible. ### Description of Change: Updated TitleView of the shellToobar when fragment becomes visible after being hidden, ensuring TitleView appears when switching back to a tab. **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Reference: N/A ### Issues Fixed: Fixes #33304 ### Screenshots | Before | After | |---------|--------| | <Video src="https://github.com/user-attachments/assets/ba231765-87bd-4de1-aa4f-86a0bb8de6c2" Width="300" Height="600"> | <Video src="https://github.com/user-attachments/assets/621e490d-ab66-4c8a-9d77-43dbd32efd93" Width="300" Height="600"> | --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Issue Details:
Shell TitleView disappears when switching between tabs on Android (regression from MAUI 9.0.30).
Root Cause:
When switching tabs, we reuses fragments by hiding/showing them if the ShellNavigationSource is ShellSectionChanged in ShellItemRendererBase class(line number 235 to 242). When a fragment becomes visible again, the TitleView handler update isn't automatically triggered, leaving the TitleView invisible.
Description of Change:
Updated TitleView of the shellToobar when fragment becomes visible after being hidden, ensuring TitleView appears when switching back to a tab.
Tested the behavior in the following platforms.
Reference:
N/A
Issues Fixed:
Fixes #33304
Screenshots
Screen.Recording.2026-01-12.at.11.31.08.AM.mov
Screen.Recording.2026-01-12.at.11.34.16.AM.mov