Skip to content

[net11.0][Android] Implement handler based Shell architecture replacing legacy renderers#34758

Open
Tamilarasan-Paranthaman wants to merge 49 commits into
net11.0from
Net11.0-Android-Shell-Handler
Open

[net11.0][Android] Implement handler based Shell architecture replacing legacy renderers#34758
Tamilarasan-Paranthaman wants to merge 49 commits into
net11.0from
Net11.0-Android-Shell-Handler

Conversation

@Tamilarasan-Paranthaman

@Tamilarasan-Paranthaman Tamilarasan-Paranthaman commented Mar 31, 2026

Copy link
Copy Markdown
Member

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!

Description

This PR introduces handler-based Shell architecture for Android, replacing the legacy renderer-based approach (ShellRenderer, ShellFlyoutRenderer, ShellItemRenderer, ShellSectionRenderer) with new handler classes that reuse standard MAUI platform components. The new architecture follows the same patterns used by FlyoutViewHandler, NavigationViewHandler, and TabbedPageManager, achieving the long-standing architectural goal of building Shell from the same building blocks as non-Shell features.

Platform: Android only. iOS/MacCatalyst continue to use legacy ShellRenderer.

Motivation

The legacy Shell renderers on Android are monolithic, tightly coupled, and duplicate functionality that already exists in standard MAUI handlers:

  • ShellFlyoutRenderer extends DrawerLayout directly (IS-A relationship) — duplicates FlyoutViewHandler drawer logic
  • ShellItemRenderer manages its own BottomNavigationView — duplicates TabbedPageManager tab logic
  • ShellSectionRenderer manages its own toolbar, navigation stack, and content tabs — duplicates NavigationViewHandler and TabbedPageManager patterns
  • Fragment management, layout inflation, and view hierarchy are all custom per-renderer

The new handler architecture:

  • Reuses MauiDrawerLayout — same shared component as FlyoutViewHandler
  • Reuses TabbedViewManager — shared tab management for both Shell and TabbedPage
  • Uses XML layout inflation — follows established MAUI patterns (navigationlayout.axml, shellitemlayout.axml, shellsectionlayout.axml)
  • Maps cleanly to Shell's virtual view hierarchy — Shell → ShellHandler, ShellItem → ShellItemHandler, ShellSection → ShellSectionHandler

Architecture Overview

Handler Hierarchy

Shell (IFlyoutView)
└── ShellHandler : ViewHandler<Shell, MauiDrawerLayout>
    ├── MauiDrawerLayout (shared with FlyoutViewHandler)
    │   ├── navigationlayout.axml (content root)
    │   └── Flyout content (ShellFlyoutTemplatedContentRenderer — reused from legacy)
    │
    └── ShellItem
        └── ShellItemHandler : ElementHandler<ShellItem, ViewPager2>
            ├── shellitemlayout.axml (CoordinatorLayout + ViewPager2)
            ├── BottomNavigationView (via TabbedViewManager)
            ├── Toolbar (shared across all sections — persists on section switch)
            └── ShellSection
                └── ShellSectionHandler : ElementHandler<ShellSection, AView>
                    ├── shellsectionlayout.axml (LinearLayout + ViewPager2)
                    ├── TabLayout (via TabbedViewManager, hidden if single content)
                    └── ShellContent → StackNavigationManager (independent nav stack per content)

Key Design Decisions

Decision Rationale
Toolbar at ShellItem level Persists across section switches — no flicker, no recreate. Sections update toolbar content, not recreate it.
LinearLayout for ShellSection (not CoordinatorLayout) CoordinatorLayout caused a white-gap bug when TabLayout was hidden (empty AppBarLayout + ScrollingViewBehavior). LinearLayout correctly reclaims space with layout_weight.
XML layout inflation Follows NavigationViewHandler/FlyoutViewHandler patterns. Resolves ?attr/ theme tokens at inflation time. Developers can override via Android resource overlays.
OffscreenPageLimit = total items Prevents FragmentStateAdapter save/restore which causes crashes (fragments lose MAUI state). Same approach as TabbedPageRenderer.
Adapter pattern for legacy interfaces ShellItemHandlerAdapter and ShellSectionHandlerAdapter implement IShellItemRenderer/IShellSectionRenderer, maintaining compatibility with ShellToolbarTracker and appearance trackers.
ITabbedViewSource interface Lightweight alternative to ITabbedView (which extends IView). Lets Shell adapters provide tab data to TabbedViewManager without 40+ IView stub members.

Customization Surface

The handler architecture preserves the full customization surface from the legacy renderer path. All factory methods, virtual hooks, and shared classes are accessible to developers.

Protected Virtual Methods (New Handler Hooks)

Handler Method Purpose
ShellItemHandler OnTabReselected(ShellSection) Customize behavior when user taps the already-selected bottom tab (e.g., scroll-to-top, refresh)
ShellItemHandler OnSectionChanged(ShellSection, bool) Intercept section/tab switches
ShellItemHandler CreateMoreBottomSheet(Action<int, BottomSheetDialog>, List<...>) Customize the "More" overflow sheet for 5+ tabs
ShellSectionHandler OnCreateNavigationAnimation(Context, bool, bool) Customize push/pop page transition animations. Wired through ShellStackNavigationManagerStackNavigationManager.OnCreateNavigationAnimation() (base is public virtual, also benefits NavigationPage)
ShellHandler 8 IShellContext factory methods All delegate to protected virtual methods: CreateTrackerForToolbar(), CreateTabLayoutAppearanceTracker(), CreateBottomNavViewAppearanceTracker(), CreateToolbarAppearanceTracker(), CreateShellFlyoutContentRenderer(), CreateShellFlyoutRenderer(), CreateFragmentForPage(), CreateShellItemTransition()

Shared Classes (Not Internalized)

Class Status Virtual Methods
ShellToolbarTracker Shared public class — used by both renderer and handler paths 17 protected virtual methods (navigation icons, search, toolbar items, back button)
ShellFlyoutRecyclerAdapter Shared — used by both paths GenerateItemList()protected virtual
Appearance trackers Shared — 3 tracker interfaces fully preserved All via IShellContext factories

Public Fragment Classes

All wrapper fragments are top-level public classes in their own files, following the one-class-per-file convention used by the legacy Shell classes. Developers can subclass them to override OnCreateView, OnResume, OnViewCreated, etc.

Fragment File Purpose
ShellItemWrapperFragment ShellItemWrapperFragment.Android.cs Hosts ShellItemHandler's layout (CoordinatorLayout + VP2 + BNV + Toolbar)
ShellSectionWrapperFragment ShellSectionWrapperFragment.Android.cs Hosts ShellSectionHandler's layout (LinearLayout + VP2 + TabLayout)
ShellContentNavigationFragment ShellContentNavigationFragment.Android.cs Hosts a ShellContent page with its own StackNavigationManager for independent navigation

Fragment Architecture

Shell handlers use wrapper fragments to integrate with Android's FragmentManager:

FragmentManager (Activity)
└── ShellItemWrapperFragment (committed by ShellHandler)
    ├── Inflates shellitemlayout.axml
    ├── Sets up ShellItemHandler with real ViewPager2 from XML
    │
    └── ChildFragmentManager
        └── ShellSectionWrapperFragment (via ViewPager2 FragmentStateAdapter)
            ├── Inflates shellsectionlayout.axml
            ├── Sets up ShellSectionHandler with real ViewPager2 from XML
            │
            └── ChildFragmentManager
                └── ShellContentNavigationFragment (via ViewPager2 FragmentStateAdapter)
                    ├── Uses StackNavigationManager for navigation
                    └── Hosts actual page content

All fragment classes are public and in their own files. All have default constructors for Android's Fragment.instantiate() reflection requirement, with null guards in OnCreateView() for graceful restoration handling.

New Files

Core Layer (src/Core/)

File Purpose
Platform/Android/MauiDrawerLayout.cs Shared DrawerLayout wrapper for FlyoutViewHandler and ShellHandler. Supports three layout modes: Flyout, SideBySide, Padding. Implements flyout width calculation per Material Design guidelines.
Platform/Android/Resources/Layout/shellitemlayout.axml XML layout for ShellItemHandler — CoordinatorLayout + ViewPager2. Toolbar, tabs, and BottomNavigationView placed into NRM slots.
Platform/Android/Resources/Layout/shellsectionlayout.axml XML layout for ShellSectionHandler — LinearLayout + ViewPager2.
Core/ITab.cs ITab interface — Title, Icon, IsEnabled for tab items in ITabbedView/ITabbedViewSource.
Primitives/TabBarPlacement.cs TabBarPlacement enum — Top / Bottom.

Controls Layer (src/Controls/)

File Purpose
Handlers/Shell/ShellHandler.Android.cs Main Shell handler. Uses MauiDrawerLayout with navigationlayout.axml. Manages flyout content, scrim brushes (including gradient via ScrimBrushDrawable), flyout behavior modes. Implements IShellContext to create handler-based renderers. 8 protected virtual factory methods.
Handlers/Shell/ShellItemHandler.Android.cs ShellItem handler. Manages bottom navigation via TabbedViewManager, shared toolbar (persists across section switches), ViewPager2 for section fragments, appearance tracking. 3 protected virtual hooks: OnTabReselected, OnSectionChanged, CreateMoreBottomSheet.
Handlers/Shell/ShellSectionHandler.Android.cs ShellSection handler. Uses ViewPager2 for content switching (unified — works for single and multiple ShellContent). TabLayout visibility controlled by item count. Each ShellContent gets its own StackNavigationManager for independent navigation. 1 protected virtual hook: OnCreateNavigationAnimation.
Handlers/Shell/ShellItemWrapperFragment.Android.cs Public fragment — hosts ShellItemHandler's layout. Inflates shellitemlayout.axml, sets up toolbar, BNV, VP2 adapter, back button handling.
Handlers/Shell/ShellSectionWrapperFragment.Android.cs Public fragment — hosts ShellSectionHandler's layout. Sets up VP2 adapter, toolbar updates on resume.
Handlers/Shell/ShellContentNavigationFragment.Android.cs Public fragment — hosts a ShellContent page with independent StackNavigationManager. Handles navigation requests, toolbar updates, tab visibility based on navigation depth.
Handlers/Shell/ShellTabbedViewAdapters.Android.cs Adapter classes: ShellItemTabbedViewAdapter (bottom tabs), ShellSectionTabbedViewAdapter (top tabs), ShellSectionTab, ShellContentTab. Bridge Shell data model to ITabbedViewSource for TabbedViewManager.
Platform/Android/ITabbedViewSource.cs Lightweight interface for TabbedViewManager consumers. Same shape as ITabbedView but doesn't extend IView.
Platform/Android/TabbedViewManager.cs Shared tab management — handles ViewPager2, BottomNavigationView, TabLayout, fragment placement, tab appearance. Used by TabbedPageManager, ShellItemHandler, and ShellSectionHandler.

Modified Files

Handler Registration

File Change
Hosting/AppHostBuilderExtensions.cs Android Shell registration now conditionally registers handlers when UseAndroidShellHandlers=true, legacy ShellRenderer otherwise.
Handlers/Shell/ShellHandler.cs Added Shell property mapper entries — routes property changes to platform-specific handler methods.

Rollout Infrastructure

File Change
Core/RuntimeFeature.cs Added UseAndroidShellHandlers feature switch (default: true). Apps can opt out with UseAndroidShellHandlers=false. Follows the same pattern as UseMaterial3.
Build.Tasks/.../Microsoft.Maui.Controls.targets Maps UseAndroidShellHandlers MSBuild property to the runtime feature switch.

Shared Component Extraction

File Change
Handlers/FlyoutView/FlyoutViewHandler.Android.cs Refactored to use MauiDrawerLayout instead of inline DrawerLayout logic. Drawer functionality extracted to shared MauiDrawerLayout.
Platform/Android/TabbedPageManager.cs Refactored to use TabbedViewManager for tab management. Reduced from ~984 lines of duplicated logic to delegating to the shared manager.
Platform/Android/Navigation/StackNavigationManager.cs Minor changes for Shell integration — supports Shell's per-content navigation stacks. Added public virtual OnCreateNavigationAnimation() for custom page transitions.

Core Interfaces

File Change
Core/ITabbedView.cs Expanded with full tab management properties: Tabs, CurrentTab, BarBackgroundColor, BarBackground, BarTextColor, UnselectedTabColor, SelectedTabColor, TabBarPlacement, OffscreenPageLimit, IsSwipePagingEnabled, IsSmoothScrollEnabled, TabsChanged event.

Compatibility Layer Fixes

File Change
ShellFlyoutTemplatedContentRenderer.cs Updated to work with both renderer and handler paths. The handler's IShellContext provides handler-based adapters while keeping the same flyout content rendering.
ShellFlyoutRecyclerAdapter.cs Minor fix for handler compatibility.
ShellSearchViewAdapter.cs Added JNI constructor on CustomFilter inner class — required for Android runtime to instantiate via reflection.
ShellToolbarTracker.cs Updated to work with handler-provided toolbar. Shared between renderer and handler paths. All 17 protected virtual methods preserved.
ShellToolbarAppearanceTracker.cs Minor update for handler compatibility.

Virtual View Changes

File Change
Element/Element.cs Changes to support handler-based Shell element hierarchy.
Shell/ShellContent.cs Added support for handler-based Shell content management.
TabbedPage/TabbedPage.cs Updated to implement expanded ITabbedView interface members.
Style.cs Minor cleanup.

PublicAPI

Updated PublicAPI.Unshipped.txt files across all TFMs for new public types and interface members:

  • MauiDrawerLayout, MauiDrawerLayout.FlyoutLayoutMode
  • ITab, ITabbedView expanded members
  • TabBarPlacement enum
  • ShellHandler, ShellItemHandler, ShellSectionHandler handler types
  • ShellItemWrapperFragment, ShellSectionWrapperFragment, ShellContentNavigationFragment fragment classes
  • Protected virtual methods: OnTabReselected, OnSectionChanged, CreateMoreBottomSheet, OnCreateNavigationAnimation

Shared Infrastructure Summary

The PR achieves the core architectural goal — Shell now uses the same building blocks as non-Shell features:

Component Shell Usage Non-Shell Usage
MauiDrawerLayout ShellHandler (flyout drawer) FlyoutViewHandler (FlyoutPage)
TabbedViewManager ShellItemHandler (bottom tabs), ShellSectionHandler (top tabs) TabbedPageManager (TabbedPage)
StackNavigationManager ShellSectionHandler (per-content nav stack) NavigationViewHandler (NavigationPage)
navigationlayout.axml ShellHandler (content root) FlyoutViewHandler, NavigationViewHandler
ITab / ITabbedView Shell adapters TabbedPage

Default-On With Opt-Out Mechanism

The Shell on Android now supports both the legacy renderer-based approach and the new handler-based approach, controlled by the UseAndroidShellHandlers MSBuild property (following the same pattern as UseMaterial3). Handler mode is now the default; setting UseAndroidShellHandlers=false keeps the legacy renderer path.

How to Opt Out (Stay On Renderer Path)

<!-- In .csproj or Directory.Build.props -->
<PropertyGroup>
    <UseAndroidShellHandlers>false</UseAndroidShellHandlers>
</PropertyGroup>

Or via command line: dotnet build -p:UseAndroidShellHandlers=false

Flow

UseAndroidShellHandlers MSBuild property → build targets → AppHostBuilderExtensions conditionally registers handlers or legacy ShellRenderer.

What Changes By Default

Element Before (Renderer) After (Handler)
Shell ShellRenderer ShellHandler → MauiDrawerLayout
ShellItem Managed by ShellItemRenderer ShellItemHandler → ViewPager2 + TabbedViewManager
ShellSection Managed by ShellSectionRenderer ShellSectionHandler → ViewPager2 + StackNavigationManager

Note: iOS/MacCatalyst are not affected — they always use ShellRenderer regardless of this setting.

Testing

  • Controls.DeviceTests.csproj relies on the runtime default (handler path).
  • Controls.TestCases.HostApp.csproj relies on the runtime default (handler path).
  • Renderer fallback coverage can be exercised by setting UseAndroidShellHandlers=false at pipeline/build invocation time.

Migration Guidance For Existing Custom Shell Renderers

This section is specifically for apps that already subclass legacy Android Shell renderers and want to enable UseAndroidShellHandlers=true.

Old -> New Mapping

Legacy customization point Handler path
ShellRenderer subclass ShellHandler subclass
ShellItemRenderer subclass ShellItemHandler subclass
ShellSectionRenderer subclass ShellSectionHandler subclass
CreateTrackerForToolbar() ShellHandler.CreateTrackerForToolbar() (protected virtual)
CreateBottomNavViewAppearanceTracker() ShellHandler.CreateBottomNavViewAppearanceTracker() (protected virtual)
CreateTabLayoutAppearanceTracker() ShellHandler.CreateTabLayoutAppearanceTracker() (protected virtual)
CreateToolbarAppearanceTracker() ShellHandler.CreateToolbarAppearanceTracker() (protected virtual)
CreateShellItemRenderer() ShellHandler.CreateShellItemRenderer() (protected virtual)
CreateShellSectionRenderer() ShellHandler.CreateShellSectionRenderer() (protected virtual)
CreateFragmentForPage() ShellHandler.CreateFragmentForPage() (protected virtual)
ShellItemRenderer.OnTabReselected() ShellItemHandler.OnTabReselected() (protected virtual)
ShellItemRenderer "More" overflow customization ShellItemHandler.CreateMoreBottomSheet() (protected virtual)

Adapter Wrapping Pattern (Important)

In the handler architecture, CreateShellItemRenderer() / CreateShellSectionRenderer() still return compatibility interfaces, but runtime behavior is bridged through handler adapters.

public class MyShellHandler : ShellHandler
{
    protected override IShellItemRenderer CreateShellItemRenderer(ShellItem shellItem)
    {
        // Register your custom ShellItemHandler and let the base factory resolve it.
        // The base implementation wraps the resolved handler with the compatibility adapter.
        return base.CreateShellItemRenderer(shellItem);
    }
}

public class MyShellItemHandler : ShellItemHandler
{
    protected override void OnTabReselected(ShellSection shellSection)
    {
        // custom behavior (scroll-to-top, refresh, pop-to-root, etc.)
        base.OnTabReselected(shellSection);
    }
}

// MauiProgram.cs
builder.ConfigureMauiHandlers(handlers =>
{
    handlers.AddHandler<ShellItem, MyShellItemHandler>();
});

Animation API Translation

Legacy Handler
SetupAnimation(ShellNavigationSource, FragmentTransaction, Page) OnCreateNavigationAnimation(Context, bool isPopping, bool enter)

What changed:

  • New API returns Android.Views.Animations.Animation? instead of mutating FragmentTransaction.
  • Direct FragmentTransaction customization is not exposed on this hook.
  • ShellNavigationSource does not map 1:1; push/pop intent maps to isPopping + enter.

Issues Fixed

Fixes #32985

Copilot AI review requested due to automatic review settings March 31, 2026 14:23
@github-actions

github-actions Bot commented Mar 31, 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 -- 34758

Or

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

@Tamilarasan-Paranthaman Tamilarasan-Paranthaman marked this pull request as draft March 31, 2026 14:24
@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Mar 31, 2026
@Tamilarasan-Paranthaman Tamilarasan-Paranthaman added platform/android area-controls-shell Shell Navigation, Routes, Tabs, Flyout labels Mar 31, 2026

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

Implements a new handler-based Shell architecture for Android (opt-in via UseAndroidShellHandlers) and refactors shared Android navigation/tab/flyout infrastructure to reduce duplication with existing MAUI handlers/managers.

Changes:

  • Added RuntimeFeature.UseAndroidShellHandlers (default false) and MSBuild plumbing to enable the feature switch.
  • Introduced shared Android components/layouts (e.g., MauiDrawerLayout, TabbedViewManager, shellitemlayout.axml, shellsectionlayout.axml) and refactored FlyoutViewHandler/TabbedPageManager to use them.
  • Updated Shell compatibility components and test projects to validate the new Android Shell handlers in CI (plus a UI test stabilization tweak).

Reviewed changes

Copilot reviewed 40 out of 40 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/Core/src/RuntimeFeature.cs Adds UseAndroidShellHandlers runtime feature switch.
src/Core/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt Public API updates for new tab abstractions/enums.
src/Core/src/PublicAPI/netstandard/PublicAPI.Unshipped.txt Public API updates for new tab abstractions/enums.
src/Core/src/PublicAPI/net/PublicAPI.Unshipped.txt Public API updates for new tab abstractions/enums.
src/Core/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt Public API updates for new tab abstractions/enums.
src/Core/src/PublicAPI/net-tizen/PublicAPI.Unshipped.txt Public API updates for new tab abstractions/enums.
src/Core/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt Public API updates for new tab abstractions/enums.
src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt Public API updates for new tab abstractions/enums.
src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt Public API updates including MauiDrawerLayout and handler signature changes.
src/Core/src/Primitives/TabBarPlacement.cs Introduces TabBarPlacement enum.
src/Core/src/Platform/Android/Resources/values/styles.xml Adds Android style for Shell TabLayout.
src/Core/src/Platform/Android/Resources/Layout/shellsectionlayout.axml New Android layout used by ShellSection handler.
src/Core/src/Platform/Android/Resources/Layout/shellitemlayout.axml New Android layout used by ShellItem handler.
src/Core/src/Platform/Android/Navigation/StackNavigationManager.cs Adds navigation request queueing and Shell integration for per-tab containers.
src/Core/src/Platform/Android/MauiDrawerLayout.cs New shared DrawerLayout wrapper used by FlyoutView/Shell.
src/Core/src/Handlers/FlyoutView/FlyoutViewHandler.Android.cs Refactors FlyoutViewHandler to use MauiDrawerLayout.
src/Core/src/Core/ITabbedView.cs Expands ITabbedView to support shared tab management surface.
src/Core/src/Core/ITab.cs Adds ITab abstraction for tab items.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/XFIssue/ShellSearchHandlerItemSizing.cs Stabilizes screenshot capture via retry/tolerance.
src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj Enables UseAndroidShellHandlers for UI test host app.
src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj Enables UseAndroidShellHandlers for device tests.
src/Controls/src/Core/TabbedPage/TabbedPage.cs Implements expanded ITabbedView surface on TabbedPage.
src/Controls/src/Core/Shell/ShellContent.cs Propagates title updates to support handler-based tab title refresh.
src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt Adds public handler types/methods for Android Shell handlers.
src/Controls/src/Core/Platform/Android/TabbedViewManager.cs New shared manager for ViewPager2 + BottomNavigationView/TabLayout behavior.
src/Controls/src/Core/Platform/Android/TabbedPageManager.cs Refactors TabbedPageManager to delegate tab UI logic to TabbedViewManager.
src/Controls/src/Core/Platform/Android/ITabbedViewSource.cs Adds internal adapter interface to supply tab data without IView.
src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs Conditionally registers Android Shell handlers based on runtime feature.
src/Controls/src/Core/Handlers/Shell/ShellTabbedViewAdapters.Android.cs Adds Shell adapters bridging ShellItem/ShellSection to tab source model.
src/Controls/src/Core/Handlers/Shell/ShellHandler.Tizen.cs Adds stub mappers to satisfy shared mapper entries.
src/Controls/src/Core/Handlers/Shell/ShellHandler.cs Extends property mapper for Android/Tizen/Windows handler scenarios.
src/Controls/src/Core/Handlers/Shell/ShellHandler.Android.cs New Android ShellHandler implementation built on MauiDrawerLayout.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellToolbarTracker.cs Compatibility updates for toolbar/search behavior and back icon progress handling.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellToolbarAppearanceTracker.cs Adds null-guard in SetAppearance.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSearchViewAdapter.cs Adds JNI ctor + null guard for filter publish.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutTemplatedContentRenderer.cs Avoids double-updates when running under new handler path; exposes update methods.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutRecyclerAdapter.cs Adds additional null/dispose safety.
src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets Maps MSBuild property to runtime feature switch.

Comment thread src/Controls/src/Core/Platform/Android/TabbedPageManager.cs
Comment thread src/Controls/src/Core/Handlers/Shell/ShellHandler.Android.cs
Comment thread src/Core/src/Platform/Android/Navigation/StackNavigationManager.cs Outdated
Comment thread src/Core/src/Platform/Android/Navigation/StackNavigationManager.cs
@vishnumenon2684 vishnumenon2684 added the community ✨ Community Contribution label Apr 1, 2026
@Tamilarasan-Paranthaman Tamilarasan-Paranthaman force-pushed the Net11.0-Android-Shell-Handler branch 2 times, most recently from b6433e8 to 0c8fa75 Compare April 6, 2026 13:23
@sheiksyedm

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).

@Tamilarasan-Paranthaman Tamilarasan-Paranthaman force-pushed the Net11.0-Android-Shell-Handler branch 2 times, most recently from 99080f6 to 603ddbc Compare April 6, 2026 14:41
@sheiksyedm

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).

@Tamilarasan-Paranthaman Tamilarasan-Paranthaman force-pushed the Net11.0-Android-Shell-Handler branch from c7bc2c4 to d695579 Compare April 9, 2026 13:57
@sheiksyedm

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).

@sheiksyedm

Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests

@azure-pipelines

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

@Tamilarasan-Paranthaman Tamilarasan-Paranthaman force-pushed the Net11.0-Android-Shell-Handler branch from 92f63a0 to c6326f5 Compare June 17, 2026 11:56
@kubaflo

kubaflo commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Verdict: NEEDS_CHANGES (confidence: high)

Re-review at HEAD c6326f52 of the large, opt-in Android handler-based Shell PR (UseAndroidShellHandlers). The latest commit resolved the prior round's blockers: the ShellSection navigation-cancellation revert (previously a no-op because PlatformView is the LinearLayout root, not the pager) is now fixed via a new internal ViewPager2? ViewPager => _viewPager; accessor; the prior AppearanceObserver/NavigationRequested teardown leaks and the "page-change callback not re-registered on reuse" warning were also addressed. All 4 models agree the direction is right but return NEEDS_CHANGES because two of those fixes introduced new defects.

Consensus findings (synthesized, 2 inline):

  • 🔴 ShellContentNavigationFragment.Android.cs:110 — the NavigationRequested leak fix is incomplete (3/4 models). The new _subscribedShellSection cache that OnDestroyView/Dispose rely on for detach is assigned only in the OnCreateView re-subscribe path (~line 75); the first-time subscribe (line 110) and ConnectAndInitialize (~line 194) leave it null. So on the normal first-creation flow the -= OnNavigationRequested is skipped (leak persists), and because _subscribedToNavigationRequested is reset to false while still attached, a later view recreation double-subscribes and fires navigation twice. Verified against HEAD: the only assignment of _subscribedShellSection is at line 75.
  • 🟠 TabbedViewManager.cs:302 — double-registers the page-change callback on first TabbedPage connect (1 model + source-verified). The constructor registers _listeners (~line 205); on the first SetElement the cleanup unregister is skipped (Element is null), so this re-register makes it double. AndroidX doesn't dedupe, so OnPageSelectedInternal runs twice and the selected page gets SendAppearing() twice. The fix is to make registration idempotent.

Dropped (1): gemini's MauiDrawerLayout.cs:101 FlyoutPage default-width regression (the FlyoutWidth getter conflates -1/MatchParent with the ~300dp Material default) is not re-raised inline: it was already posted in the prior round, and FlyoutViewHandler.MapFlyoutWidth runs after MapFlyout and re-applies the handler's correct MatchParent (-1) to the flyout's LayoutParameters.Width, so the narrow width most likely does not manifest on a normal FlyoutPage connect. Worth confirming against the failing API-30 snapshot before re-posting rather than blocking on it. CI (maui-pr) for this HEAD is still pending, so the PR is not LGTM-eligible regardless of the above.

Multi-model review (gpt-5.5 · opus-4.8 · opus-4.6 · gemini-3.1-pro). Comments only — not a formal approval.

@vishnumenon2684

Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests

@azure-pipelines

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

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 community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants