[LayoutDiagnostics] Added runtime layout diagnostics API for profiling measure/arrange counts per element type. Includes a floating overlay visible over modals and bottom sheets, automatic snapshot capture during page and bottom sheet lifecycle, per-instance thrashing detection, and JSON export.#849
Open
[LayoutDiagnostics] Added runtime layout diagnostics API for profiling measure/arrange counts per element type. Includes a floating overlay visible over modals and bottom sheets, automatic snapshot capture during page and bottom sheet lifecycle, per-instance thrashing detection, and JSON export.#849
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new runtime “Layout Diagnostics” feature to DIPS.Mobile.UI to profile .NET MAUI layout behavior (measure/arrange counts) at runtime, including an always-on-top overlay and automatic snapshot capture tied to page/bottom sheet lifecycles.
Changes:
- Introduces
LayoutDiagnosticsService+LayoutDiagnosticsSnapshotfor capturing and exporting layout metric snapshots. - Adds platform-specific overlay hosting (iOS
UIWindow, Android re-parenting above dialogs) and hooks overlay z-ordering into Android fragment lifecycle. - Updates apps (Components/Playground) to enable MAUI metrics and adds sample “Diagnostics” pages + changelog/wiki/prompt updates.
Reviewed changes
Copilot reviewed 25 out of 25 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
wiki/Layout-Diagnostics.md |
New wiki page documenting the layout diagnostics feature and usage. |
src/library/DIPS.Mobile.UI/Components/Pages/ContentPage.cs |
Auto begin/end snapshot hooks added to page lifecycle. |
src/library/DIPS.Mobile.UI/Components/BottomSheets/BottomSheet.cs |
Auto begin/end snapshot hooks added to bottom sheet open/close. |
src/library/DIPS.Mobile.UI/API/Library/Android/FragmentLifeCycleCallback.cs |
Tracks dialog stack and elevates/restores overlay above dialogs. |
src/library/DIPS.Mobile.UI/API/Diagnostics/LayoutDiagnosticsService.cs |
New shared diagnostics service using MeterListener + snapshot management. |
src/library/DIPS.Mobile.UI/API/Diagnostics/LayoutDiagnosticsSnapshot.cs |
New snapshot model, warnings analysis, and JSON export helpers. |
src/library/DIPS.Mobile.UI/API/Diagnostics/LayoutDiagnosticsOverlay.cs |
New MAUI overlay UI (pill + expanded panel) for controlling/viewing diagnostics. |
src/library/DIPS.Mobile.UI/API/Diagnostics/iOS/LayoutDiagnosticsService.cs |
iOS overlay implementation hosted in a separate passthrough UIWindow. |
src/library/DIPS.Mobile.UI/API/Diagnostics/Android/LayoutDiagnosticsService.cs |
Android overlay implementation added to activity content / dialog decor view. |
src/library/DIPS.Mobile.UI/API/Diagnostics/dotnet/LayoutDiagnosticsService.cs |
Desktop stub partial implementation. |
src/app/Playground/Playground.csproj |
Adds diagnostics package dependency needed for AddMetrics(). |
src/app/Playground/MauiProgram.cs |
Registers metrics (AddMetrics) for MAUI diagnostics instruments. |
src/app/Playground/DiagnosticsSamples/LayoutDiagnosticsPage.xaml |
New Playground diagnostics UI page (XAML). |
src/app/Playground/DiagnosticsSamples/LayoutDiagnosticsPage.xaml.cs |
New Playground diagnostics UI logic and snapshot rendering. |
src/app/Playground/App.xaml.cs |
Adds a Diagnostics tab to the Playground Shell. |
src/app/Components/Components.csproj |
Adds diagnostics package dependency needed for AddMetrics(). |
src/app/Components/MauiProgram.cs |
Registers metrics (AddMetrics) for MAUI diagnostics instruments. |
src/app/Components/DiagnosticsSamples/LayoutDiagnosticsPage.xaml |
New Components-app diagnostics UI page (XAML). |
src/app/Components/DiagnosticsSamples/LayoutDiagnosticsPage.xaml.cs |
New Components-app diagnostics UI logic and snapshot rendering. |
src/app/Components/App.xaml.cs |
Adds a Diagnostics tab to the Components Shell. |
src/Directory.Packages.props |
Adds central package version for Microsoft.Extensions.Diagnostics. |
global.json |
Bumps pinned .NET SDK version. |
CHANGELOG.md |
Adds a minor version entry for the new diagnostics feature. |
.github/skills/design-system-usage/SKILL.md |
Adds guidance for design token/style usage in C# UI. |
.github/prompts/enable-layout-diagnostics.prompt.md |
Adds a how-to prompt for enabling layout diagnostics in an app. |
Comments suppressed due to low confidence (1)
src/library/DIPS.Mobile.UI/Components/Pages/ContentPage.cs:88
- Snapshots are started in
OnAppearing()but ended inOnNavigatingFrom(). This doesn't match the PR description/wiki (which referenceOnNavigatedTo/OnDisappearing), and it can leave a snapshot running across non-navigation disappear scenarios (e.g., a modal covering the page) until another snapshot begins or diagnostics are disabled. Consider ending the page snapshot inOnDisappearing()(and updating docs accordingly) to ensure snapshots are always closed when the page is no longer visible.
protected override void OnAppearing()
{
base.OnAppearing();
HasAppeared = true;
// Complete previous snapshot (captures outgoing page + transition layout)
// and start new snapshot for this page's ongoing layout
LayoutDiagnosticsService.BeginSnapshot($"Page: {GetType().Name}");
HideOrShowFloatingNavigationMenu();
#if __ANDROID__
// Update status bar color for this page (works for both modal and non-modal)
StatusBarHandler.TrySetStatusBarColor(this, StatusBarColor);
#endif
}
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Agent-Logs-Url: https://github.com/DIPSAS/DIPS.Mobile.UI/sessions/eb3d2f31-1908-4999-89ec-bb2e2b05989b Co-authored-by: Vetle444 <35739538+Vetle444@users.noreply.github.com>
auto-merge was automatically disabled
April 27, 2026 06:46
Head branch was pushed to by a user without write access
Contributor
Author
|
@copilot Fix all remaining comments |
- LayoutDiagnosticsOverlay: remove unused Icons using, replace FontSize=12 with Sizes.GetSize(SizeName.size_3), remove MinimumWidthRequest=220 magic number, replace hardcoded top margin 54 with size_14 token - Move wiki/Layout-Diagnostics.md → wiki/Guides/Layout-Diagnostics.md - Playground/App.xaml.cs: remove unused DIPS.Mobile.UI.API.Diagnostics using - enable-layout-diagnostics.prompt.md: fix reference file paths to actual DiagnosticsSamples/LayoutDiagnosticsPage.xaml locations - FragmentLifeCycleCallback: call base.OnFragmentDestroyed unconditionally Agent-Logs-Url: https://github.com/DIPSAS/DIPS.Mobile.UI/sessions/4e81c711-23bd-4e18-9d04-932d3010ea73 Co-authored-by: Vetle444 <35739538+Vetle444@users.noreply.github.com>
Contributor
All remaining comments addressed in 9632452:
|
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.
Description of Change
Add a runtime layout diagnostics API (
LayoutDiagnosticsService) for profiling .NET MAUI layout performance on iOS and Android.What it does:
System.Diagnostics.Metricsinstruments (maui.layout.measure_count,maui.layout.arrange_count) viaMeterListenerto count every measure and arrange call per element type and instanceContentPageandBottomSheetlifecycle (OnNavigatedTo/OnAppearing → OnDisappearing)Floating overlay:
UIWindowatUIWindowLevel.Alert - 1with touch passthrough viaHitTestoverride, pinned full-screen so MAUI handles internal layoutMatchParentlayout with MAUI-managed positioning + automatic re-parenting to dialogDecorViewvia centralizedFragmentLifeCycleCallbackwith dialog stack tracking for nested dialogsBackground — Measure & Arrange:
MAUI uses a two-phase layout process (Microsoft Learn):
IView.Measure()calculates desired size given constraints. May be called multiple times speculatively.IView.Arrange()assigns final position and bounds.Deeply nested layouts with complex constraints can cause exponential re-measurement (layout thrashing). This tool makes that visible at runtime.
Public API:
LayoutDiagnosticsService— Static service:Initialize(),Teardown(),Enable(),Disable(),Toggle(),ClearSnapshots(),ExportAllToJson(),IsEnabled,IsInitialized,CompletedSnapshots,CurrentSnapshot,SnapshotCompletedeventLayoutDiagnosticsSnapshot— Per-navigation snapshot:SourceName,TotalMeasureCount,TotalArrangeCount,MeasureCountsByType,MeasureInstancesByType,Warnings,ToJson(),ToCompactString(),ToDetailedString()Files added (library):
API/Diagnostics/LayoutDiagnosticsService.cs— Shared service with MeterListenerAPI/Diagnostics/LayoutDiagnosticsSnapshot.cs— Snapshot data modelAPI/Diagnostics/LayoutDiagnosticsOverlay.cs— Overlay UI using Border + RoundRectangle, design tokensAPI/Diagnostics/iOS/LayoutDiagnosticsService.cs— iOS UIWindow approach (full-screen pinning, HitTest passthrough)API/Diagnostics/Android/LayoutDiagnosticsService.cs— Android MatchParent + dialog elevationAPI/Diagnostics/dotnet/LayoutDiagnosticsService.cs— Desktop stubFiles modified (library):
FragmentLifeCycleCallback.cs— Centralized dialog fragment lifecycle handling for overlay z-ordering with dialog stackContentPage.cs— AutoBeginSnapshot/EndSnapshoton navigationBottomSheet.cs— AutoBeginSnapshot/EndSnapshoton open/closePrerequisites:
builder.Services.AddMetrics()in MauiProgram.cs