Skip to content

[Android] [ShellHandler] Extend existing device tests to cover both Renderer and Handler code paths - #36328

Merged
kubaflo merged 17 commits into
dotnet:net11.0from
Vignesh-SF3580:fix-AndroidShellHandlerDeviceTests
Jul 28, 2026
Merged

[Android] [ShellHandler] Extend existing device tests to cover both Renderer and Handler code paths#36328
kubaflo merged 17 commits into
dotnet:net11.0from
Vignesh-SF3580:fix-AndroidShellHandlerDeviceTests

Conversation

@Vignesh-SF3580

Copy link
Copy Markdown
Contributor

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!

Summary

Adds Android device test coverage for the Handler-based Shell, Modal, and Window implementations alongside the existing Renderer-based tests, allowing both Android implementations to run in CI. Also fixes a bottom navigation menu update issue in TabbedViewManager.cs that was uncovered while adding this coverage.

Changes

  • Added RendererHandlerVariant.cs to define shared [Trait] constants (AndroidShellRenderer and AndroidShellHandler) for identifying Renderer and Handler test variants.
  • Updated xUnitCustomizations.cs to read the Variant trait (Android only) and prefix test display names with [Renderer] or [Handler], making it easy to identify the implementation that failed in CI.
  • Updated ShellTests, ModalTests, WindowTests, ShellFlyoutTests, ShellTabBarTests, and their Android/iOS partials to make the required setup methods virtual and tag the existing tests with the Renderer trait. This allows the same test implementations to be reused by the Handler subclasses instead of duplicating them.
  • Added ShellHandlerSubclasses.Android.cs, which contains ShellHandlerTests_Shell, ModalHandlerTests, and WindowHandlerTests. These subclasses reuse the existing test implementations while registering the Handler implementation on Android and are tagged with the Handler trait.

Source Fix – TabbedViewManager.cs

Issue:
SetupBottomNavigationView() called menu.Clear() during tab updates, recreating IMenuItem instances. The Handler-based tests validate menu item identity, which caused the tests to fail.
Fix:
Updated the menu setup logic to use BottomNavigationViewUtils.SetupMenu(), which updates existing menu items instead of recreating them.

Test Fix – PushingNavigationPageModallyWithShellShowsToolbarCorrectly

Issue:
The existing GetPlatformToolbar() helper supported ShellRenderer but not ShellHandler. In the Handler implementation, the toolbar is hosted within an outer CoordinatorLayout, so the existing lookup logic did not work.
Fix:
Added an IsBackButtonVisible helper and a GetShellHandlerToolbar() helper to locate the toolbar through the nested CoordinatorLayout hierarchy.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 36328

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 36328"

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Jul 3, 2026
@github-actions github-actions Bot added area-controls-shell Shell Navigation, Routes, Tabs, Flyout platform/android platform/ios platform/macos macOS / Mac Catalyst labels Jul 3, 2026
@kubaflo

This comment has been minimized.

@github-actions github-actions Bot added the s/agent-review-in-progress AI review is currently running for this PR label Jul 3, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expert Review — 2 findings

See inline comments for details.

Comment thread src/Controls/src/Core/Platform/Android/TabbedViewManager.cs Outdated
Comment thread src/Controls/src/Core/Platform/Android/TabbedViewManager.cs
@MauiBot MauiBot added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Jul 3, 2026
MauiBot

This comment was marked as outdated.

@MauiBot MauiBot removed the s/agent-review-in-progress AI review is currently running for this PR label Jul 3, 2026
@kubaflo

kubaflo commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@kubaflo

This comment has been minimized.

@github-actions

This comment has been minimized.

@sheiksyedm
sheiksyedm marked this pull request as ready for review July 6, 2026 13:27
Copilot AI review requested due to automatic review settings July 6, 2026 13:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends Android device test coverage for Shell/Modal/Window by reusing the existing renderer-based test bodies and adding handler-based subclasses, and it adjusts Android tab menu setup to preserve BottomNavigationView menu item identity for the handler implementation.

Changes:

  • Introduces a shared Variant trait (Renderer/Handler) and updates Android xUnit display names to prefix [Renderer]/[Handler] to distinguish reused test bodies.
  • Refactors Shell/Modal/Window device tests to allow reuse via virtual setup/helpers and adds Android handler-based subclasses that register the native handlers.
  • Updates TabbedViewManager.SetupBottomNavigationView() to use BottomNavigationViewUtils.SetupMenu() (incremental updates) instead of recreating menu items via menu.Clear().

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/TestUtils/src/DeviceTests/xUnitCustomizations.cs Prefixes Android test display names with a variant label based on a Variant trait.
src/Controls/tests/DeviceTests/Elements/Window/WindowTests.cs Tags renderer variant and makes builder setup overridable for handler subclasses.
src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs Tags renderer variant, makes setup overridable, and updates tests to use the non-generic window helper for reuse.
src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.Android.cs Refactors Android helpers to operate on IShellContext so tests can run against renderer or handler.
src/Controls/tests/DeviceTests/Elements/Shell/ShellTabBarTests.cs Makes shared runner virtual and reuses non-generic handler/window path for subclassing.
src/Controls/tests/DeviceTests/Elements/Shell/ShellTabBarTests.Android.cs Updates Android tab lookup to use IShellContext instead of renderer-specific types.
src/Controls/tests/DeviceTests/Elements/Shell/ShellHandlerSubclasses.Android.cs Adds Android handler-based subclasses that register native Shell/Tabbed/etc handlers and reuse existing test bodies.
src/Controls/tests/DeviceTests/Elements/Shell/ShellFlyoutTests.iOS.cs Adjusts to new shared callback signature and accesses handler via shell.Handler.
src/Controls/tests/DeviceTests/Elements/Shell/ShellFlyoutTests.cs Refactors shared flyout tests to a Func<Shell, Task> callback to enable Android handler subclass reuse.
src/Controls/tests/DeviceTests/Elements/Shell/ShellFlyoutTests.Android.cs Updates Android flyout test to use IShellContext from shell.Handler.
src/Controls/tests/DeviceTests/Elements/Shell/RendererHandlerVariant.cs Defines shared Variant trait constants used by device tests and Android display name prefixing.
src/Controls/tests/DeviceTests/Elements/Modal/ModalTests.cs Tags renderer variant and makes builder setup overridable for handler subclasses.
src/Controls/tests/DeviceTests/ControlsHandlerTestBase.Android.cs Makes IsBackButtonVisible virtual so handler variants can override toolbar traversal.
src/Controls/src/Core/Platform/Android/TabbedViewManager.cs Switches bottom navigation menu setup to incremental updates via BottomNavigationViewUtils.SetupMenu().

Comment thread src/Controls/src/Core/Platform/Android/TabbedViewManager.cs Outdated
Copilot AI review requested due to automatic review settings July 27, 2026 12:53
@Vignesh-SF3580
Vignesh-SF3580 force-pushed the fix-AndroidShellHandlerDeviceTests branch from 084ce87 to d49cb2e Compare July 27, 2026 12:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Comment on lines 832 to 833
catch (Exception ex)
{
Copilot AI review requested due to automatic review settings July 27, 2026 13:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated no new comments.

@Vignesh-SF3580

Copy link
Copy Markdown
Contributor Author

Could you please resolve conflicts and check the ai's suggestions?

@kubaflo I have resolved the conflicts and reviewed the AI suggestions. Both suggestions appear to be invalid, so no additional changes were required.

@vishnumenon2684

Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests , maui-pr-devicetests

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 2 pipeline(s).

@kubaflo

This comment has been minimized.

@github-actions github-actions Bot added the s/agent-review-in-progress AI review is currently running for this PR label Jul 27, 2026
@MauiBot

This comment has been minimized.

@MauiBot MauiBot removed the s/agent-review-in-progress AI review is currently running for this PR label Jul 27, 2026
@Vignesh-SF3580

Copy link
Copy Markdown
Contributor Author

AI Review Summary

@Vignesh-SF3580 — new AI review results are available based on this last commit: 1643845.

Gate Inconclusive Confidence Low Platform Android

🗂️ Review Sessions — click to expand

🚦 Gate — Test Before & After Fix

Gate Result: ⚠️ INCONCLUSIVE

Platform: ANDROID · Base: net11.0 · Merge base: 414cc7f3

🩺 Could not verify — environment/infrastructure error. The gate ran the tests but hit an environment error (the test app crashed or exited before writing its results, an emulator/simulator/Appium/XHarness flake, or an empty/invalid result file), so it could not record a real pass/fail. The ⚠️ ENV ERROR marks below are infrastructure, not test failures — this is not a problem with your PR. Comment /review to retry on a fresh agent.

App crashed during test run (XHarness exit 80 APP_CRASH)

Test Without Fix (expect FAIL) With Fix (expect PASS)
📱 ModalTests ModalTests ⚠️ ENV ERROR ⚠️ ENV ERROR
📱 ShellTests (ReusedBottomTabReappliesEnabledState, MoreOverflowItemIsReusedNotRecreated) Category=Shell ⚠️ ENV ERROR ⚠️ ENV ERROR
🔴 Without fix — 📱 ModalTests: ⚠️ ENV ERROR · 971s
(no coded error found; showing last 1200 chars)

i.controls.devicetests.zip
�[40m�[32minfo�[39m�[22m�[49m: <<XHARNESS_RESULT_START>>
      {
        "version": 1,
        "machineName": "runnervmtroe5",
        "exitCode": 80,
        "exitCodeName": "APP_CRASH",
        "platform": "android",
        "device": "emulator-5554",
        "deviceOsVersion": "API 30",
        "architecture": "x86_64",
        "files": [
          {
            "name": "adb-logcat-com.microsoft.maui.controls.devicetests-default.log",
            "type": "logcat"
          },
          {
            "name": "adb-bugreport-com.microsoft.maui.controls.devicetests.zip",
            "type": "bugreport"
          }
        ]
      }
      <<XHARNESS_RESULT_END>>
�[40m�[32minfo�[39m�[22m�[49m: Attempting to remove apk 'com.microsoft.maui.controls.devicetests'..
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 uninstall com.microsoft.maui.controls.devicetests'
�[40m�[32minfo�[39m�[22m�[49m: Successfully uninstalled com.microsoft.maui.controls.devicetests
XHarness exit code: 80 (APP_CRASH)
  Tests completed with exit code: 80

🟢 With fix — 📱 ModalTests: ⚠️ ENV ERROR · 659s
(no coded error found; showing last 1200 chars)

i.controls.devicetests.zip
�[40m�[32minfo�[39m�[22m�[49m: <<XHARNESS_RESULT_START>>
      {
        "version": 1,
        "machineName": "runnervmtroe5",
        "exitCode": 80,
        "exitCodeName": "APP_CRASH",
        "platform": "android",
        "device": "emulator-5554",
        "deviceOsVersion": "API 30",
        "architecture": "x86_64",
        "files": [
          {
            "name": "adb-logcat-com.microsoft.maui.controls.devicetests-default.log",
            "type": "logcat"
          },
          {
            "name": "adb-bugreport-com.microsoft.maui.controls.devicetests.zip",
            "type": "bugreport"
          }
        ]
      }
      <<XHARNESS_RESULT_END>>
�[40m�[32minfo�[39m�[22m�[49m: Attempting to remove apk 'com.microsoft.maui.controls.devicetests'..
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 uninstall com.microsoft.maui.controls.devicetests'
�[40m�[32minfo�[39m�[22m�[49m: Successfully uninstalled com.microsoft.maui.controls.devicetests
XHarness exit code: 80 (APP_CRASH)
  Tests completed with exit code: 80

🔴 Without fix — 📱 ShellTests (ReusedBottomTabReappliesEnabledState, MoreOverflowItemIsReusedNotRecreated): ⚠️ ENV ERROR · 596s
(no coded error found; showing last 1200 chars)

i.controls.devicetests.zip
�[40m�[32minfo�[39m�[22m�[49m: <<XHARNESS_RESULT_START>>
      {
        "version": 1,
        "machineName": "runnervmtroe5",
        "exitCode": 80,
        "exitCodeName": "APP_CRASH",
        "platform": "android",
        "device": "emulator-5554",
        "deviceOsVersion": "API 30",
        "architecture": "x86_64",
        "files": [
          {
            "name": "adb-logcat-com.microsoft.maui.controls.devicetests-default.log",
            "type": "logcat"
          },
          {
            "name": "adb-bugreport-com.microsoft.maui.controls.devicetests.zip",
            "type": "bugreport"
          }
        ]
      }
      <<XHARNESS_RESULT_END>>
�[40m�[32minfo�[39m�[22m�[49m: Attempting to remove apk 'com.microsoft.maui.controls.devicetests'..
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 uninstall com.microsoft.maui.controls.devicetests'
�[40m�[32minfo�[39m�[22m�[49m: Successfully uninstalled com.microsoft.maui.controls.devicetests
XHarness exit code: 80 (APP_CRASH)
  Tests completed with exit code: 80

🟢 With fix — 📱 ShellTests (ReusedBottomTabReappliesEnabledState, MoreOverflowItemIsReusedNotRecreated): ⚠️ ENV ERROR · 630s
(no coded error found; showing last 1200 chars)

i.controls.devicetests.zip
�[40m�[32minfo�[39m�[22m�[49m: <<XHARNESS_RESULT_START>>
      {
        "version": 1,
        "machineName": "runnervmtroe5",
        "exitCode": 80,
        "exitCodeName": "APP_CRASH",
        "platform": "android",
        "device": "emulator-5554",
        "deviceOsVersion": "API 30",
        "architecture": "x86_64",
        "files": [
          {
            "name": "adb-logcat-com.microsoft.maui.controls.devicetests-default.log",
            "type": "logcat"
          },
          {
            "name": "adb-bugreport-com.microsoft.maui.controls.devicetests.zip",
            "type": "bugreport"
          }
        ]
      }
      <<XHARNESS_RESULT_END>>
�[40m�[32minfo�[39m�[22m�[49m: Attempting to remove apk 'com.microsoft.maui.controls.devicetests'..
�[40m�[37mdbug�[39m�[22m�[49m: Executing command: '/home/vsts/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26230.4/runtimes/any/native/adb/linux/adb -s emulator-5554 uninstall com.microsoft.maui.controls.devicetests'
�[40m�[32minfo�[39m�[22m�[49m: Successfully uninstalled com.microsoft.maui.controls.devicetests
XHarness exit code: 80 (APP_CRASH)
  Tests completed with exit code: 80

⚠️ Failure Details

  • ⚠️ ModalTests without fix: App crashed during test run (XHarness exit 80 APP_CRASH)
  • ⚠️ ShellTests (ReusedBottomTabReappliesEnabledState, MoreOverflowItemIsReusedNotRecreated) without fix: App crashed during test run (XHarness exit 80 APP_CRASH)
  • ⚠️ ModalTests with fix: App crashed during test run (XHarness exit 80 APP_CRASH)
  • ⚠️ ShellTests (ReusedBottomTabReappliesEnabledState, MoreOverflowItemIsReusedNotRecreated) with fix: App crashed during test run (XHarness exit 80 APP_CRASH)

📁 Fix files reverted (2 files)

  • src/Controls/src/Core/Platform/Android/BottomNavigationViewUtils.cs
  • src/Controls/src/Core/Platform/Android/TabbedViewManager.cs

📱 UI Tests — Button,Label,Layout

Detected UI test categories: Button,Label,Layout

Deep UI tests — 359 passed, 0 failed across 3 categories on platform-pool agent (replaces in-process counts above).

🧪 UI Test Execution Results (deep, platform pool)

Category Tests Snapshot diffs
Button 71/73 ✓ —
Label 96/98 ✓ —
Layout 192/195 ✓ —
📎 Download drop-deep-uitests artifact (TRX + snapshot diffs)
📋 Pre-Flight — Context & Validation

Issue: #36328 - Android Shell bottom-tab menu reuse/state regression PR: #36328 - Android Shell/TabbedView bottom navigation menu reuse fix Platforms Affected: Android Files Changed: 2 implementation, 1 test

Key Findings

  • Public GitHub API access was rate-limited and gh is unauthenticated, so PR narrative and prior review surfaces could not be retrieved. Local branch diff and existing gate artifacts were used.
  • The PR modifies Android bottom navigation infrastructure: BottomNavigationViewUtils.SetupMenu, SetMenuItemIcon, and TabbedViewManager.SetupBottomNavigationView.
  • The recorded gate was inconclusive due Android XHarness APP_CRASH infrastructure errors for ModalTests and Shell regression tests; this is not evidence that the PR fix failed.
  • Regression coverage in the branch includes Android Shell tests for reused tab enabled state and More overflow item reuse.

Code Review Summary

Verdict: NEEDS_DISCUSSION Confidence: low Errors: 0 | Warnings: 0 | Suggestions: 0

Key code review findings:

  • ℹ No high-confidence code correctness findings found by the code-review sub-agent.
  • ℹ Blast radius: Android Shell/TabbedView bottom-tab setup path runs for all Android Shell bottom-tab instances; platform UI plumbing limits confidence.
  • ℹ Failure mode checked: stale async icon loads are guarded by pending-source identity before applying the drawable.
  • ℹ Failure mode checked: reused menu items reapply enabled state and icon tint; null icon source clears stale icon.
  • ℹ Failure mode checked: reused More item uses SetChecked rather than SelectedItemId, avoiding accidental bottom-sheet display.

Fix Candidates

Source Approach Test Result Files Changed Notes

PR PR #36328 Reuse BottomNavigationViewUtils.SetupMenu from TabbedViewManager, update reused IMenuItem title/icon/enabled/checked state, add weak pending-source guard for async icon loads, and preserve More item identity. ⚠️ INCONCLUSIVE (Gate) BottomNavigationViewUtils.cs, TabbedViewManager.cs, ShellTests.Android.cs Gate hit Android XHarness APP_CRASH infra errors, not a real pass/fail.
🔬 Code Review — Deep Analysis

Code Review — PR #36328

Independent Assessment

What this changes: Android Shell/TabbedView bottom navigation now reuses existing menu items, reapplies state/tint on reuse, guards stale async icon loads, and adds/reuses Android Shell handler device-test coverage with renderer/handler display-name variants. Inferred motivation: Expand native Android ShellHandler test coverage while fixing bottom-tab recreation/race behavior.

Reconciliation with PR Narrative

Author claims: Full PR description was unavailable: gh is unauthenticated and GitHub web/API fallback was blocked/rate-limited. Patch subjects indicate "Added handler device tests", "Reused the existing tests", "differentiate Renderer and Handler", and BottomNavigation updates. Agreement/disagreement: Local diff matches those claims.

Prior Review Reconciliation

Could not retrieve prior review surfaces. All three required gh queries—top-level reviews, inline comments, and issue comments—failed with authentication error. No prior ❌ findings were accessible for reconciliation.

Blast Radius Assessment

  • Runs for all instances: Yes, Android Shell/TabbedView bottom-tab setup uses the changed production path.
  • Startup impact: Limited to Shell/tab layout initialization, not process startup.
  • Static/shared state: Yes, ConditionalWeakTable<IMenuItem, ImageSource> tracks pending icon sources with weak keys.
  • Handler/platform risk: Android platform UI plumbing; confidence capped at medium before CI/prior-review limitations.

CI Status

  • Required-check result: undetermined — gh pr checks 36328 --required failed: unauthenticated.
  • Classification: undetermined.
  • Action taken: capped confidence. Local targeted validation succeeded:
    dotnet build src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj -f net11.0-android --no-restore -p:TreatWarningsAsErrors=true.

Findings

No high-confidence code correctness findings found. Expert reviewer also produced inline-findings.json with [].

Failure-Mode Probing

  • Stale async icon load after menu item reuse: guarded by pending-source identity check before applying drawable.
  • Null icon source on reused menu item: clears stale icon and reapplies tint callback.
  • Handler disconnect/reconnect: production changes don't add persistent subscriptions; existing cleanup remains.
  • More-tab reuse/overflow changes: selection is reapplied without SelectedItemId, avoiding accidental sheet display.

Verdict: NEEDS_DISCUSSION

Confidence: low Summary: Code review found no concrete code issues, and targeted Android build passed. However, required CI and prior-review reconciliation could not be verified due unavailable GitHub authentication/API access, so the skill rules prohibit an LGTM verdict.

🛠️ Fix — Analysis & Comparison

Fix Candidates

Source Approach Test Result Files Changed Notes

1 try-fix Manager-owned bottom-nav slot reconciliation in TabbedViewManager; restore BottomNavigationViewUtils to baseline; use manager-level icon-load generation guard. ⚠️ Build-only validated 2 files Compiles, but not demonstrably better than PR because it duplicates reconciliation policy in TabbedViewManager.
2 try-fix Event-scoped OnTabsCollectionChanged fast path for overflow-only and trailing removals; fallback to original full setup otherwise. ❌ Failed expert review 2 files Build succeeded, but expert review found Shell 2-tabs -> 1-tab leaves bottom nav visible because the fast path bypasses one-tab hide logic.
PR PR #36328 Incremental in-place updates in BottomNavigationViewUtils.SetupMenu, TabbedViewManager delegates to it, stale async icon guard via weak table, reapply reused-item state/tint and More checked state. ⚠️ INCONCLUSIVE (Gate) 3 files Gate hit Android XHarness APP_CRASH infra errors; no concrete code issue found in pre-flight code review.

Cross-Pollination

Model Round New Ideas? Details
maui-expert-reviewer 1 Yes Candidate 1: manager-owned reconciliation in TabbedViewManager.
maui-expert-reviewer 2 Yes Candidate 2: event-scoped fast path for remove deltas.
maui-expert-reviewer 3 No No remaining non-trivial approaches: alternatives either duplicate PR-style reconciliation elsewhere, only reapply state after rebuild without preserving identity, or become narrow fast paths like candidate 2.
Exhausted: Yes Selected Fix: PR's fix — The alternatives either duplicate reconciliation logic in a riskier location or fail important Shell state transitions. The PR approach is broader and was not contradicted by code review, though gate/device verification remains inconclusive due infrastructure.

🏁 Report — Final Recommendation

Comparative Fix Report — PR #36328

Candidates compared

Rank Candidate Regression result Assessment
1 pr ⚠️ Inconclusive gate, no code-review findings Best overall. It centralizes bottom navigation reconciliation in BottomNavigationViewUtils.SetupMenu(), preserves stable IMenuItem identity where possible, reapplies state/tint on reuse, guards stale async icon loads, and preserves Shell one-tab/overflow behavior.
1 pr-plus-reviewer ⚠️ Inconclusive gate, no code-review findings Equivalent to pr. The expert reviewer produced [], so no sandbox changes were applied.
3 try-fix-1 ⚠️ Build-only validated Viable but weaker than the PR. It moves reconciliation policy into TabbedViewManager, duplicating logic that already belongs in the shared bottom navigation utility and increasing future drift risk. Its manager-wide icon generation guard is broader than the PR's per-item/per-source stale-load guard.
4 try-fix-2 ❌ Failed expert review Must rank below candidates without failed regression/expert-review results. Its event-scoped fast path bypasses full setup on a 2-tabs-to-1-tab Shell removal, leaving bottom navigation visible when existing Shell behavior should hide it.

Winning candidate

pr

pr and pr-plus-reviewer are functionally identical because the expert reviewer found no actionable feedback to apply. The raw PR fix is selected as the winner to avoid implying that a changed sandbox variant exists.

Rationale

The PR fix addresses the root problem at the shared bottom navigation reconciliation layer rather than adding narrow collection-change fast paths or duplicating menu reconciliation inside TabbedViewManager. It also covers edge cases the alternatives either missed or handled less cleanly: stale async icon loads, reused enabled/checked/tinted state, overflow More identity, and Shell's one-tab hide behavior.

The gate was inconclusive due infrastructure, not a demonstrated failure. Under the ranking rule, try-fix-2 is below the non-failing candidates because it has a concrete Shell state regression.

🧭 Next Steps — review latest findings

There are no major or valid concerns raised.
The gate phase failed due to an environment issue (APP_CRASH, XHarness exit code 80) in both the with-fix and without-fix runs, indicating it is unrelated to the PR changes. No code review concerns, suggestions, or alternative fixes were raised.

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review Summary

@Vignesh-SF3580 — new AI review results are available based on this last commit: 1643845.

Gate Inconclusive Confidence Low Platform Android


🗂️ Review Sessions — click to expand
🚦 Gate — Test Before & After Fix

Gate: Test Verification (Failure-Only Mode)

Result: ⚠️ INCONCLUSIVE

This is a test-only change (no fix files detected in the diff), so the gate only verifies that the new/changed tests fail against the merge base — proving they reproduce the bug they target.

Platform: ANDROID
Merge base: f3a08b3a

Test Type Outcome
ModalTests DeviceTest 🛠️ BUILD ERROR
ShellTests (ReusedBottomTabReappliesEnabledState, MoreOverflowItemIsReusedNotRecreated) DeviceTest 🛠️ BUILD ERROR
Diagnostics
  • ModalTests: Build failed: /home/vsts/work/1/s/.dotnet/sdk/11.0.100-preview.7.26365.101/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.Sdk.ImportWorkloads.targets(38,5): error NETSDK1147: To build this project, the following work...
  • ShellTests (ReusedBottomTabReappliesEnabledState, MoreOverflowItemIsReusedNotRecreated): Build failed: /home/vsts/work/1/s/.dotnet/sdk/11.0.100-preview.7.26365.101/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.Sdk.ImportWorkloads.targets(38,5): error NETSDK1147: To build this project, the following work...

📋 Pre-Flight — Context & Validation

Issue: N/A - No linked issue found in the public PR metadata
PR: #36328 - [Android] [ShellHandler] Extend existing device tests to cover both Renderer and Handler code paths
Platforms Affected: Android
Files Changed: 2 implementation, 13 test

Key Findings

  • PR #36328 adds Android Shell renderer/handler variant device-test coverage and changes Android bottom-navigation setup to reuse native menu items instead of clearing/recreating them.
  • The production BottomNavigationViewUtils.SetupMenu() reuse path appears to address prior menu-item state/icon concerns, including enabled state, checked state, icon tint, null icon clearing, and stale async icon loads.
  • Pre-flight code review found unresolved test/build blockers: unused shellContext locals, inherited native handler flyout tests still using renderer-oriented toolbar lookup, and an overflow reuse test that does not wait on native menu mutation.
  • Required CI status could not be queried because gh is unauthenticated in this environment; the provided gate result is inconclusive and was not re-run.

Code Review Summary

Verdict: NEEDS_CHANGES
Confidence: low
Errors: 2 | Warnings: 1 | Suggestions: 0

Key code review findings:

  • ShellTests.Android.cs:72, 109, 224, 316, 633 contain unused shellContext locals that can fail warnings-as-errors builds.
  • ShellTests.Android.cs:693 calls GetPlatformToolbar((IPlatformViewHandler)shellContext) from OpenFlyout(), which does not traverse the native Android ShellHandler toolbar hierarchy used by handler-variant tests.
  • ShellTests.Android.cs:533 waits on managed Items.Count, which changes synchronously and does not prove the native BottomNavigationView processed the overflow update.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #36328 Route TabbedViewManager bottom navigation setup through BottomNavigationViewUtils.SetupMenu() to reuse IMenuItems and preserve state/icon updates. ⚠️ INCONCLUSIVE (Gate) BottomNavigationViewUtils.cs, TabbedViewManager.cs, Android Shell device tests Original PR fix; gate already inconclusive and not re-run.

🔬 Code Review — Deep Analysis

Code Review — PR #36328

Independent Assessment

What this changes: Adds Android device-test coverage for Shell renderer/handler variants, refactors Shell tests to use IShellContext, and changes Android bottom-navigation menu setup to reuse IMenuItems while preserving icon/state updates.
Inferred motivation: Exercise the newer Android Shell handler path and fix menu-item identity/state issues exposed by that coverage.

Reconciliation with PR Narrative

Author claims: Adds renderer/handler variant test coverage and fixes TabbedViewManager bottom navigation updates by reusing menu items.
Agreement/disagreement: Matches the code. I found unresolved test/build issues in the added/refactored handler coverage.

Prior Review Reconciliation

Prior ❌ Error Finding Source Status Evidence
Reused menu items did not reapply enabled/selection/tint or guard async icon races MauiBot inline reviews ✅ Fixed BottomNavigationViewUtils.cs:129-135, 162-165, 172-184, 197-234; TabbedViewManager.cs:790-797, 822-830
Unused shellContext locals cause warnings-as-errors build failures MauiBot inline reviews ❌ Unresolved Still present at ShellTests.Android.cs:72, 109, 224, 316, 633; repo has TreatWarningsAsErrors=true in Directory.Build.props:6
Native Shell handler flyout tests still use toolbar lookup that lacks native handler traversal MauiBot inline review ❌ Unresolved OpenFlyout still calls GetPlatformToolbar((IPlatformViewHandler)shellContext) at ShellTests.Android.cs:693; native traversal only exists in ShellHandlerSubclasses.Android.cs:64-93
ConditionalWeakTable null icon source concern MauiBot inline review 🔄 Obsolete / not reproduced Current null branch clears icon at BottomNavigationViewUtils.cs:206-210; AddOrUpdate only rejects null keys

Blast Radius Assessment

  • Runs for all instances: Yes, Android Shell/TabbedView bottom-tab setup uses the changed production path.
  • Startup impact: No process startup impact; affects Shell/tab initialization and updates.
  • Static/shared state: Yes, weak-table state tracks pending icon sources per IMenuItem.

CI Status

  • Required-check result: undetermined
  • Classification: tool unavailable — gh pr checks 36328 --repo dotnet/maui --required failed because gh is unauthenticated.
  • Action taken: confidence capped low; no GitHub comments posted.

Findings

❌ Error — Unused locals will fail warnings-as-errors builds

src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.Android.cs:72, 109, 224, 316, and 633 still declare var shellContext = (IShellContext)shell.Handler; without using it. With repo-wide TreatWarningsAsErrors=true, CS0219 breaks the device-test build. Remove the unused declarations or use them.

❌ Error — Handler flyout tests still use the renderer toolbar lookup

ShellTests.Android.cs:693 still finds the hamburger via GetPlatformToolbar((IPlatformViewHandler)shellContext). For NativeShellHandler, the PR itself adds separate toolbar traversal in ShellHandlerSubclasses.Android.cs:64-93, but only uses it for IsBackButtonVisible. Inherited handler flyout tests that call OpenFlyout can still throw Unable to find Drawer Button.

⚠️ Warning — Overflow reuse test does not prove the native menu updated

ShellTests.Android.cs:533 waits for shell.CurrentItem.Items.Count == 6, which is true immediately after RemoveAt(6). The subsequent menu assertions were already true before the change, so a handler that never processes the overflow update could still pass. Wait on a native-menu change that only occurs after the update.

Failure-Mode Probing

  • Null icon source: current code clears the reused item icon before returning; looks safe.
  • Stale async icon load: guarded by per-item pending source checks when using SetMenuItemIcon.
  • Native handler flyout open: still fails through base OpenFlyout toolbar lookup.
  • Build with warnings-as-errors: unresolved unused locals produce compile failures.

Verdict: NEEDS_CHANGES

Confidence: low
Summary: The production bottom-navigation approach looks mostly addressed, but the PR still contains concrete test/build blockers. CI status could not be verified due unavailable gh auth, further capping confidence.


🛠️ Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix-1 Add virtual Android Shell test helpers (GetFlyoutToolbar/GetDrawerButton), override native handler toolbar lookup in the handler subclass, remove unused locals, and strengthen overflow wait by mutating a visible title. ⚠️ BLOCKED 2 files Environment blocked before candidate compilation; addresses pre-flight test-helper blockers with narrow blast radius.
2 try-fix-2 Centralize native ShellHandler toolbar lookup in ControlsHandlerTestBase.Android.cs:GetPlatformToolbar, remove unused locals, and strengthen overflow wait by visible slot retitle/reuse. ⚠️ BLOCKED 2 files Environment blocked before candidate compilation; broader test-helper blast radius but avoids new virtual hooks.
3 try-fix-3 Replace PR's BottomNavigationViewUtils.SetupMenu() call with local TabbedViewManager slot reconciliation and per-item icon-load version guards. ⚠️ BLOCKED 1 file Environment blocked before candidate compilation; meaningful production-code alternative but riskier because it duplicates menu reconciliation logic.
PR PR #36328 Use shared BottomNavigationViewUtils.SetupMenu() from TabbedViewManager for incremental bottom-navigation item reuse. ⚠️ INCONCLUSIVE (Gate) 2 implementation files + tests Existing PR fix; not considered passing because gate was inconclusive.

Cross-Pollination

Model/Reviewer Round New Ideas? Details
maui-expert-reviewer 1 Yes try-fix-1: test-helper virtual hooks and subclass override.
maui-expert-reviewer 2 Yes try-fix-2: central shared Android toolbar helper strategy.
maui-expert-reviewer 3 Yes try-fix-3: production-code slot reconciliation alternative.
maui-expert-reviewer Exhaustion No Remaining variants are refactorings of the same test-helper or bottom-nav reconciliation approaches.

Test / Environment Summary

All candidate test commands were blocked before executing Android tests or compiling the candidate changes:

  • Initial net11.0-android build failed with NETSDK1242 because Mono runtime Android projects are not supported in .NET 11+ without the required CoreCLR targeting configuration.
  • The allowed dotnet workload restore src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj attempt succeeded and installed the Android workload.
  • net10.0-android targeted builds then failed at src/Maui.InTree.targets because required MAUI MSBuild tasks were not built.
  • The prerequisite dotnet build Microsoft.Maui.BuildTasks.slnf --no-restore attempt failed due missing assets, unsupported net11.0-android Mono runtime targeting, and missing .NET Framework 4.7.2 reference assemblies on Linux.

Per-candidate details are in:

  • CustomAgentLogsTmp/PRState/36328/PRAgent/try-fix-1/content.md
  • CustomAgentLogsTmp/PRState/36328/PRAgent/try-fix-2/content.md
  • CustomAgentLogsTmp/PRState/36328/PRAgent/try-fix-3/content.md

Exhausted: Yes
Selected Fix: No candidate selected — none passed validation. On code merits, try-fix-1 and try-fix-2 directly address the unresolved test/build blockers; try-fix-3 is a meaningful but higher-risk production alternative. The PR's existing shared SetupMenu() production fix remains simpler than try-fix-3, but the PR still needs the test-helper/build issues from pre-flight resolved before it can be considered better validated.


📝 Recommended PR Title & Description

Assessment: ✏️ Recommend updating — the current description is strong for the raw PR, but the selected winning candidate adds test-helper/build reliability fixes that are not described.

Recommended title

[Android] ShellHandler: Cover handler device-test paths and reuse bottom-tab menu items

Recommended description

### Summary
Adds Android device test coverage for the Handler-based Shell, Modal, and Window implementations alongside the existing Renderer-based tests, allowing both Android implementations to run in CI. Also fixes a bottom navigation menu update issue in TabbedViewManager.cs that was uncovered while adding this coverage.

### Changes

- Added RendererHandlerVariant.cs to define shared [Trait] constants (AndroidShellRenderer and AndroidShellHandler) for identifying Renderer and Handler test variants.
- Updated xUnitCustomizations.cs to read the Variant trait (Android only) and prefix test display names with [Renderer] or [Handler], making it easy to identify the implementation that failed in CI.
- Updated ShellTests, ModalTests, WindowTests, ShellFlyoutTests, ShellTabBarTests, and their Android/iOS partials to make the required setup methods virtual and tag the existing tests with the Renderer trait. This allows the same test implementations to be reused by the Handler subclasses instead of duplicating them.
- Added ShellHandlerSubclasses.Android.cs, which contains ShellHandlerTests_Shell, ModalHandlerTests, and WindowHandlerTests. These subclasses reuse the existing test implementations while registering the Handler implementation on Android and are tagged with the Handler trait.
- Removed unused Android Shell test locals that can fail warnings-as-errors builds.
- Added overridable Android flyout toolbar/drawer-button lookup helpers so inherited Shell handler flyout tests can locate the native ShellHandler toolbar hierarchy.
- Strengthened the bottom-tab overflow reuse test so it waits for an observable native BottomNavigationView menu update instead of the synchronously updated managed Items.Count.

### Source Fix – TabbedViewManager.cs
**Issue:**
SetupBottomNavigationView() called menu.Clear() during tab updates, recreating IMenuItem instances. The Handler-based tests validate menu item identity, which caused the tests to fail.

**Fix:**
Updated the menu setup logic to use BottomNavigationViewUtils.SetupMenu(), which updates existing menu items instead of recreating them.

### Test Fix – PushingNavigationPageModallyWithShellShowsToolbarCorrectly
**Issue:**
The existing GetPlatformToolbar() helper supported ShellRenderer but not ShellHandler. In the Handler implementation, the toolbar is hosted within an outer CoordinatorLayout, so the existing lookup logic did not work.

**Fix:**
Added an IsBackButtonVisible helper and a GetShellHandlerToolbar() helper to locate the toolbar through the nested CoordinatorLayout hierarchy.

### Test Fix – ShellHandler flyout lookup
**Issue:**
Inherited Android flyout tests still opened the flyout through the renderer-oriented toolbar lookup path, which does not traverse the native ShellHandler toolbar hierarchy.

**Fix:**
Added overridable GetFlyoutToolbar() and GetDrawerButton() helpers and overrode the ShellHandler variant to use the native ShellHandler toolbar traversal.

🏁 Report — Final Recommendation

Comparative Report — PR #36328

Candidate ranking

Rank Candidate Regression/gate result Assessment
1 try-fix-1 ⚠️ Blocked / unverified Best code-merit candidate. It preserves the PR's shared production BottomNavigationViewUtils.SetupMenu() approach and narrowly fixes the device-test/build blockers: removes unused locals, routes flyout drawer lookup through overridable helpers with a native ShellHandler override, and strengthens the overflow reuse wait.
2 try-fix-2 ⚠️ Blocked / unverified Also addresses the unused locals and overflow wait, and centralizes native ShellHandler toolbar lookup in ControlsHandlerTestBase.Android.cs. Slightly lower than try-fix-1 because the helper-level change has broader blast radius across Android device tests.
3 pr-plus-reviewer ⚠️ Inconclusive / unverified Improves the raw PR by applying the expert reviewer's overflow-test reliability feedback, but leaves the pre-flight unused-local build issue and inherited handler flyout toolbar lookup issue unresolved.
4 pr ⚠️ Inconclusive / unverified Production fix is directionally sound and simpler than try-fix-3, but the raw PR still has the expert overflow wait warning plus the pre-flight test/build blockers.
5 try-fix-3 ⚠️ Blocked / unverified Meaningful production-code alternative, but riskier: it duplicates bottom-navigation reconciliation in TabbedViewManager instead of reusing the established shared utility path and does not address the test-helper/build blockers.

No candidate has a passing regression/gate result. The gate and all try-fix validations were blocked or inconclusive due environment/build prerequisites, so none are treated as failed regression tests. Because no candidate passed validation, the winner is selected on code correctness, blast radius, and how completely it addresses known review findings.

Winner

Selected candidate: try-fix-1

try-fix-1 is the strongest candidate because it keeps the PR's production fix intact while adding the smallest targeted test-side corrections needed for the new Android handler coverage to be reliable. Compared with pr-plus-reviewer, it includes the same native-menu wait strengthening and also resolves the two pre-flight blockers that the expert reviewer did not include in its final inline JSON. Compared with try-fix-2, it avoids changing shared Android test helper behavior for unrelated callers.

Notes on PR metadata

Because the selected winner is not the raw PR fix, the PR description should be updated if this candidate is applied. The current description accurately describes the raw PR's production fix and added handler coverage, but it does not mention the additional try-fix-1 refinements: removing unused shellContext locals, adding overridable flyout toolbar/drawer-button lookup for native ShellHandler, and strengthening the overflow reuse test wait.


🧭 Next Steps — alternative fix proposed (try-fix-1)

Automated review — alternative fix proposed

The expert-reviewer evaluation compared the PR fix against automatically generated candidates and selected try-fix-1 as the strongest fix.

Why: try-fix-1 wins because it preserves the PR production fix while narrowly addressing the known Android handler test/build blockers and the expert reviewer overflow-wait feedback. No candidate passed validation; all results were blocked or inconclusive, so this ranking is based on code merits and blast radius.

Please consider applying the candidate diff below (or use it as guidance). Once you push an update, this workflow will re-trigger and re-evaluate.

Candidate diff (try-fix-1)
diff --git a/src/Controls/tests/DeviceTests/Elements/Shell/ShellHandlerSubclasses.Android.cs b/src/Controls/tests/DeviceTests/Elements/Shell/ShellHandlerSubclasses.Android.cs
index 2c91281c94..41db963c8e 100644
--- a/src/Controls/tests/DeviceTests/Elements/Shell/ShellHandlerSubclasses.Android.cs
+++ b/src/Controls/tests/DeviceTests/Elements/Shell/ShellHandlerSubclasses.Android.cs
@@ -61,7 +61,15 @@ namespace Microsoft.Maui.DeviceTests
 			return false;
 		}
 
-		MaterialToolbar GetShellHandlerToolbar(IElementHandler handler)
+		protected override MaterialToolbar GetFlyoutToolbar(IShellContext shellContext)
+		{
+			if (shellContext is NativeShellHandler nativeShell)
+				return GetShellHandlerToolbar(nativeShell);
+
+			return base.GetFlyoutToolbar(shellContext);
+		}
+
+		protected MaterialToolbar GetShellHandlerToolbar(IElementHandler handler)
 		{
 			// Direct NativeShellHandler: toolbar lives in nested CoordinatorLayout of shell.CurrentPage.
 			if (handler is NativeShellHandler nativeShell)
diff --git a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.Android.cs b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.Android.cs
index 86e7a4c4d8..2fd97d52f8 100644
--- a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.Android.cs
+++ b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.Android.cs
@@ -69,7 +69,6 @@ namespace Microsoft.Maui.DeviceTests
 
 			await CreateHandlerAndAddToWindow(shell, async () =>
 			{
-				var shellContext = (IShellContext)shell.Handler;
 				await OnLoadedAsync(page1);
 				await shell.GoToAsync("//Item2");
 				await shell.GoToAsync("..");
@@ -106,7 +105,6 @@ namespace Microsoft.Maui.DeviceTests
 
 			await CreateHandlerAndAddToWindow(shell, async () =>
 			{
-				var shellContext = (IShellContext)shell.Handler;
 				await Task.Delay(100);
 
 				var platformToolbar = GetPlatformToolbar((IPlatformViewHandler)shell.Handler);
@@ -221,7 +219,6 @@ namespace Microsoft.Maui.DeviceTests
 
 			await CreateHandlerAndAddToWindow(shell, async () =>
 			{
-				var shellContext = (IShellContext)shell.Handler;
 				await OnFrameSetToNotEmpty(footer);
 				Assert.True(Math.Abs(20 - footer.Frame.Width) < 1);
 				Assert.True(footer.Frame.Height > 0);
@@ -313,7 +310,6 @@ namespace Microsoft.Maui.DeviceTests
 
 			await CreateHandlerAndAddToWindow(shell, async () =>
 			{
-				var shellContext = (IShellContext)shell.Handler;
 				await Task.Delay(100);
 				var headerPlatformView = header.ToPlatform();
 				var appBar = headerPlatformView.GetParentOfType<AppBarLayout>();
@@ -528,9 +524,12 @@ namespace Microsoft.Maui.DeviceTests
 				// (6 tabs remain, still over the 5-item max) — the "More" IMenuItem
 				// must be reused, not recreated, since it's not structurally changing.
 				shell.CurrentItem.Items.RemoveAt(6);
+				shell.CurrentItem.Items[0].Title = "Updated Tab 1";
 
-				// let the change propagate
-				await AssertEventually(() => shell.CurrentItem.Items.Count == 6);
+				// Wait for a native menu update, not the already-updated managed collection count.
+				await AssertEventually(() =>
+					bottomView.Menu.Size() == 5 &&
+					bottomView.Menu.GetItem(0).TitleFormatted?.ToString() == "Updated Tab 1");
 
 				menu = bottomView.Menu;
 				Assert.Equal(5, menu.Size());
@@ -630,7 +629,6 @@ namespace Microsoft.Maui.DeviceTests
 
 			await CreateHandlerAndAddToWindow(shell, async () =>
 			{
-				var shellContext = (IShellContext)shell.Handler;
 				await OnLoadedAsync(shell.CurrentPage);
 				await OnNavigatedToAsync(shell.CurrentPage);
 
@@ -690,8 +688,7 @@ namespace Microsoft.Maui.DeviceTests
 				await Task.Delay(10);
 
 			var hamburger =
-				GetPlatformToolbar((IPlatformViewHandler)shellContext).GetChildrenOfType<AppCompatImageButton>().FirstOrDefault() ??
-				throw new InvalidOperationException("Unable to find Drawer Button");
+				GetDrawerButton(shellContext);
 
 			timeOut = timeOut ?? TimeSpan.FromSeconds(2);
 
@@ -708,6 +705,19 @@ namespace Microsoft.Maui.DeviceTests
 			}
 		}
 
+		protected virtual MaterialToolbar GetFlyoutToolbar(IShellContext shellContext)
+		{
+			return GetPlatformToolbar((IPlatformViewHandler)shellContext);
+		}
+
+		protected virtual AppCompatImageButton GetDrawerButton(IShellContext shellContext)
+		{
+			return GetFlyoutToolbar(shellContext)?
+				.GetChildrenOfType<AppCompatImageButton>()
+				.FirstOrDefault()
+				?? throw new InvalidOperationException("Unable to find Drawer Button");
+		}
+
 		protected virtual async Task<double> ScrollFlyoutToBottom(IShellContext shellContext)
 		{
 			DrawerLayout dl = shellContext.CurrentDrawerLayout;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-shell Shell Navigation, Routes, Tabs, Flyout partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android platform/ios platform/macos macOS / Mac Catalyst s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants