[net11.0][Android] Implement handler based Shell architecture replacing legacy renderers#34758
Open
Tamilarasan-Paranthaman wants to merge 40 commits into
Open
[net11.0][Android] Implement handler based Shell architecture replacing legacy renderers#34758Tamilarasan-Paranthaman wants to merge 40 commits into
Tamilarasan-Paranthaman wants to merge 40 commits into
Conversation
Contributor
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34758Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34758" |
Contributor
There was a problem hiding this comment.
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(defaultfalse) and MSBuild plumbing to enable the feature switch. - Introduced shared Android components/layouts (e.g.,
MauiDrawerLayout,TabbedViewManager,shellitemlayout.axml,shellsectionlayout.axml) and refactoredFlyoutViewHandler/TabbedPageManagerto 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. |
b6433e8 to
0c8fa75
Compare
Contributor
|
/azp run maui-pr-uitests , maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
99080f6 to
603ddbc
Compare
Contributor
|
/azp run maui-pr-uitests , maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
c7bc2c4 to
d695579
Compare
Contributor
|
/azp run maui-pr-uitests , maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
This was referenced Apr 13, 2026
Open
3b5baeb to
7265fdf
Compare
Contributor
|
/azp run maui-pr-uitests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
7b7eda5 to
e7572f9
Compare
This was referenced May 25, 2026
Contributor
|
/azp run maui-pr-uitests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 byFlyoutViewHandler,NavigationViewHandler, andTabbedPageManager, 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:
ShellFlyoutRendererextendsDrawerLayoutdirectly (IS-A relationship) — duplicatesFlyoutViewHandlerdrawer logicShellItemRenderermanages its ownBottomNavigationView— duplicatesTabbedPageManagertab logicShellSectionRenderermanages its own toolbar, navigation stack, and content tabs — duplicatesNavigationViewHandlerandTabbedPageManagerpatternsThe new handler architecture:
MauiDrawerLayout— same shared component asFlyoutViewHandlerTabbedViewManager— shared tab management for both Shell andTabbedPagenavigationlayout.axml,shellitemlayout.axml,shellsectionlayout.axml)Shell → ShellHandler,ShellItem → ShellItemHandler,ShellSection → ShellSectionHandlerArchitecture Overview
Handler Hierarchy
Key Design Decisions
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)
ShellItemHandlerOnTabReselected(ShellSection)ShellItemHandlerOnSectionChanged(ShellSection, bool)ShellItemHandlerCreateMoreBottomSheet(Action<int, BottomSheetDialog>, List<...>)ShellSectionHandlerOnCreateNavigationAnimation(Context, bool, bool)ShellStackNavigationManager→StackNavigationManager.OnCreateNavigationAnimation()(base ispublic virtual, also benefitsNavigationPage)ShellHandlerIShellContextfactory methodsprotected virtualmethods:CreateTrackerForToolbar(),CreateTabLayoutAppearanceTracker(),CreateBottomNavViewAppearanceTracker(),CreateToolbarAppearanceTracker(),CreateShellFlyoutContentRenderer(),CreateShellFlyoutRenderer(),CreateFragmentForPage(),CreateShellItemTransition()Shared Classes (Not Internalized)
ShellToolbarTrackerpublic class— used by both renderer and handler pathsprotected virtualmethods (navigation icons, search, toolbar items, back button)ShellFlyoutRecyclerAdapterGenerateItemList()—protected virtualIShellContextfactoriesPublic Fragment Classes
All wrapper fragments are top-level
publicclasses in their own files, following the one-class-per-file convention used by the legacy Shell classes. Developers can subclass them to overrideOnCreateView,OnResume,OnViewCreated, etc.ShellItemWrapperFragmentShellItemWrapperFragment.Android.csShellSectionWrapperFragmentShellSectionWrapperFragment.Android.csShellContentNavigationFragmentShellContentNavigationFragment.Android.csFragment Architecture
Shell handlers use wrapper fragments to integrate with Android's
FragmentManager:All fragment classes are public and in their own files. All have default constructors for Android's
Fragment.instantiate()reflection requirement, with null guards inOnCreateView()for graceful restoration handling.New Files
Core Layer (
src/Core/)Controls Layer (
src/Controls/)protected virtualfactory methods.protected virtualhooks:OnTabReselected,OnSectionChanged,CreateMoreBottomSheet.protected virtualhook:OnCreateNavigationAnimation.Modified Files
Handler Registration
Opt-In Infrastructure
Shared Component Extraction
public virtual OnCreateNavigationAnimation()for custom page transitions.Core Interfaces
Compatibility Layer Fixes
protected virtualmethods preserved.Virtual View Changes
PublicAPI
Updated
PublicAPI.Unshipped.txtfiles across all TFMs for new public types and interface members:MauiDrawerLayout,MauiDrawerLayout.FlyoutLayoutModeITab,ITabbedViewexpanded membersTabBarPlacementenumShellHandler,ShellItemHandler,ShellSectionHandlerhandler typesShellItemWrapperFragment,ShellSectionWrapperFragment,ShellContentNavigationFragmentfragment classesOnTabReselected,OnSectionChanged,CreateMoreBottomSheet,OnCreateNavigationAnimationShared Infrastructure Summary
The PR achieves the core architectural goal — Shell now uses the same building blocks as non-Shell features:
Opt-In Mechanism
The Shell on Android now supports both the legacy renderer-based approach and the new handler-based approach, controlled by the
UseAndroidShellHandlersMSBuild property (following the same pattern asUseMaterial3).How to Enable
Or via command line:
dotnet build -p:UseAndroidShellHandlers=trueFlow
UseAndroidShellHandlersMSBuild property → build targets →AppHostBuilderExtensionsconditionally registers handlers or legacyShellRenderer.What Changes When Enabled
Testing
UseAndroidShellHandlers=trueis set in the following test/sample projects for CI validation:Controls.TestCases.HostApp.csproj— UI testsControls.DeviceTests.csproj— Device testsIssues Fixed
Fixes #32985