MAUI Phase 5 Slice 1: fix AndroidView fallback sizing for self-drawing views#270
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR closes Phase 5 Slice 1 by adding investigation-only sample pages that verify various MAUI controls (Shapes, GraphicsView, WebView, HybridWebView, and unsupported layouts) render correctly through the existing AndroidView fallback path in ComposeWalker. No new Compose-backed handlers or library code changes are introduced — the PR demonstrates that the stock MAUI handlers work as-is when hosted inside a Compose composition via AndroidView interop.
Changes:
- Five new sample pages (
ShapesPage,GraphicsViewPage,WebViewPage,HybridWebViewPage,LayoutsPage) with XAML + code-behind exercising every Phase 5 control through unmodified stock handlers. - Shell route registrations and
HomePagecatalog entries wiring the new pages into the sample app, plus ahybridroot/index.htmlraw asset for the HybridWebView JS bridge round-trip demo. docs/maui-backend.mdupdated with a comprehensive Phase 5 Slice 1 subsection: per-control verdict matrix, verification gap disclosure, intentional exclusions, and follow-up tracking.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
Pages/ShapesPage.xaml(.cs) |
New XAML page exercising all seven Shapes subclasses via the stock ShapeViewHandler fallback. |
Pages/GraphicsViewPage.xaml(.cs) |
New page with a synthetic IDrawable sparkline + tap-to-reshuffle, verifying GraphicsViewHandler fallback + Invalidate(). |
Pages/WebViewPage.xaml(.cs) |
New page with HtmlWebViewSource inline JS counter + about:blank URL baseline. |
Pages/HybridWebViewPage.xaml(.cs) |
New page verifying HybridWebView JS bridge round-trip (SendRawMessage/RawMessageReceived). |
Pages/LayoutsPage.xaml(.cs) |
New page hosting Grid, AbsoluteLayout, FlexLayout via the AndroidView fallback. |
Resources/Raw/hybridroot/index.html |
Minimal HTML + JS for the HybridWebView bridge demo. |
AppShell.xaml.cs |
Shell route registrations for the five new pages. |
HomePage.xaml.cs |
Catalog entries for the five new demos. |
docs/maui-backend.md |
Replaces brief Phase 5 stub with full investigation report, per-control matrix, and follow-up plan. |
…g views
The original commit on this branch claimed every Phase 5 control worked
unchanged through `ComposeWalker`'s `AndroidView { factory =
view.ToPlatform(MauiContext) }` fallback. On-device verification on a
Pixel 5 proved that wrong for self-drawing views: `MauiShapeView` and
`PlatformGraphicsView` painted nothing - even forcing
`platformView.SetBackgroundColor(Color.Magenta)` was invisible, which
proves the View was getting a 0 x 0 layout slot.
Root cause: the fallback never applied a Compose `Modifier.Size` (or
`.Width`/`.Height`) derived from MAUI's `WidthRequest`/`HeightRequest`.
Compose handed `AndroidView` an unbounded slot, the embedded View
measured wrap-content, and self-drawing Views with no intrinsic size
collapsed and their `Drawable` painted nothing. Compose-native handlers
like `BoxViewHandler` already did this themselves via
`IComposeHandler.BuildNode`; the fallback was missing the same mapping.
Fix sits inside `ComposeWalker.Render`: read `WidthRequest`/`HeightRequest`
off the `Microsoft.Maui.Controls.VisualElement` and translate to
`Modifier.Size` / `Modifier.Width` / `Modifier.FillMaxWidth().Height(...)`,
matching `BoxViewHandler`. No new public surface, no new handler.
Sample pages reduced to the two with Compose-specific behaviour worth
keeping as on-device reproducers for the bug:
* `Pages/ShapesPage.xaml(.cs)` - all seven shape kinds
(Rectangle / RoundRectangle / Ellipse / Line / Polygon / Polyline /
Path) plus a fill-width Rectangle that exercises the
`WidthRequest = -1, HeightRequest >= 0` branch.
* `Pages/GraphicsViewPage.xaml(.cs)` - `IDrawable` paints a random
zigzag plot; tap-to-reshuffle bumps the seed and `Invalidate()`s.
The other three pages from the original slice (`WebViewPage`,
`HybridWebViewPage`, `LayoutsPage`) are deleted - they exercised
controls that already work via fallback (or already ship in working
form across other sample pages, in the case of `Grid` /
`AbsoluteLayout` / `FlexLayout` on `HomePage.xaml`) and didn't surface
new Compose-specific behaviour worth the gallery slot.
`docs/maui-backend.md` Phase 5 section rewritten to reflect the truth:
per-control matrix updated (every shape + GraphicsView marked "works
via fallback after the size-modifier fix"), `HybridWebView` moved to
"deferred", verification matrix replaced with a concrete on-device
verdict on a Pixel 5.
Verified:
* `dotnet test src/Microsoft.AndroidX.Compose.SourceGenerators.Tests`
= 155 passed.
* `dotnet build src/Microsoft.AndroidX.Compose` clean.
* `dotnet build src/Microsoft.AndroidX.Compose.Maui` clean.
* `dotnet build src/Microsoft.AndroidX.Compose.Maui.Sample` clean.
* `dotnet build src/Microsoft.AndroidX.Compose.Maui.Sample -t:Install`
clean.
* `dotnet build src/Microsoft.AndroidX.Compose.Gallery` clean.
* On-device on a Pixel 5: deployed, navigated to Shapes (all seven
shape kinds + fill-width Rectangle render correctly) and to
GraphicsView (canvas paints, tap-to-reshuffle redraws the plot and
bumps the seed badge from 0 to 1).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
816b24d to
1607f14
Compare
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.
On-device verification turned up a real bug, fixed in this slice.
TL;DR
The original commit on this branch claimed every Phase 5 control worked unchanged through
ComposeWalker'sAndroidView { factory = view.ToPlatform(MauiContext) }fallback — without any device verification. On a Pixel 5,ShapesandGraphicsViewpaint nothing: their stock Android views (MauiShapeView,PlatformGraphicsView) collapse to 0 × 0 and theirDrawablenever draws. (ForcingplatformView.SetBackgroundColor(Color.Magenta)was invisible — proved zero size, not zero paint.)Root cause: the fallback never applied a Compose
Modifier.Sizederived from MAUI'sWidthRequest/HeightRequest. Compose handedAndroidViewan unbounded slot. Compose-native handlers likeBoxViewHandleralready did this themselves; the fallback was the only path missing it.Fix is one switch expression in
ComposeWalker.Render. No new handlers, no new public surface.Per-control verdict (on-device, Pixel 5)
IDrawable)Invalidate()repaints — tap-to-reshuffle bumps the seed and the canvas redraws.ViewHandlerover AndroidWebView); not exercised to avoid the package dependency.HomePage.xaml'sGridchrome since Phase 1. Sample page deleted.Sample page changes
Kept (on-device reproducers for the bug):
Pages/ShapesPage.xaml(.cs)Pages/GraphicsViewPage.xaml(.cs)Deleted (the controls work via the fallback after the fix and the demos surfaced no Compose-specific behaviour worth a gallery slot):
Pages/WebViewPage.xaml(.cs)Pages/HybridWebViewPage.xaml(.cs)+Resources/Raw/hybridroot/index.htmlPages/LayoutsPage.xaml(.cs)Out of scope
Canvas+DrawScope— parked behind Bind drawing primitives: Canvas, Modifier.drawBehind/drawWithContent, DrawScope, Brush, Path, Shape factories #64.GraphicsViewviaDrawScopeshim — parked behind Bind drawing primitives: Canvas, Modifier.drawBehind/drawWithContent, DrawScope, Brush, Path, Shape factories #64.Layout {}adapter (closes per-leafComposeViewislands inside fallback-hosted layouts) — parked behind Bind customLayout {}primitive — Measurable / Placeable / MeasureScope #144.Verification
dotnet test src/Microsoft.AndroidX.Compose.SourceGenerators.Tests= 155 passed.dotnet build src/Microsoft.AndroidX.Composeclean.dotnet build src/Microsoft.AndroidX.Compose.Mauiclean.dotnet build src/Microsoft.AndroidX.Compose.Maui.Sampleclean (zero warnings, zero errors).dotnet build src/Microsoft.AndroidX.Compose.Maui.Sample -t:Installclean.dotnet build src/Microsoft.AndroidX.Compose.Galleryclean.