Skip to content

[release/10.0.1xx-sr10] [Android] Fix scrolling performance in shadowed containers - #37312

Merged
kubaflo merged 1 commit into
release/10.0.1xx-sr10from
backport/pr-37291-to-release/10.0.1xx-sr10
Aug 11, 2026
Merged

kubaflo merged 1 commit into
release/10.0.1xx-sr10from
backport/pr-37291-to-release/10.0.1xx-sr10

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 11, 2026 •

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!

Backport of #37291 to release/10.0.1xx-sr10.

/cc @kubaflo

<!-- Please let the below note in for people that find this PR -->
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Root Cause

#35623 made `PlatformWrapperView.onDescendantInvalidated()` call
`invalidate()` for every descendant update whenever the wrapper had a
shadow. That keeps an immediate child animation such as a shadowed
`Switch` in sync, but it also makes scrolling descendants redraw the
entire shadowed container for every item update.

The complete reproduction from
[MrLazyLee/ScrollPerformance](https://github.com/MrLazyLee/ScrollPerformance)
has two large shadow wrappers around the `CollectionView`:

- The CommunityToolkit popup's default shadow.
- An explicit shadow on the inner `Border`.

Instrumentation over four up/down scroll cycles recorded:

| Wrapper | Descendant invalidations | Immediate-child invalidations |
|---|---:|---:|
| Popup, 1079 x 1678 | 1,859 | 3 |
| Border, 1026 x 1306 | 1,803 | 2 |

The current code therefore forces thousands of full-popup redraws even
though only five invalidations originate from the immediate children
whose shadows may need to move.

### Description of Change

Only invalidate a shadow wrapper when Android reports that the
invalidation target is its immediate child (`child == target`). Deeper
descendants continue to redraw through their own RenderNodes without
forcing the whole shadowed ancestor to re-record its display list.

This preserves the #35623 behavior for controls such as `Switch`, while
removing the scrolling regression for nested `CollectionView` and
`ScrollView` content.

### Verification

The author reproduction was built with the exact 10.0.90 source and the
same locally-built native AAR for both control and patched runs. Each
row below used the same emulator and automated eight-cycle scroll
sequence without screen recording:

| Variant | 50th percentile | 90th percentile | Slow UI-thread frames |
|---|---:|---:|---:|
| 10.0.80 | 34 ms | 53 ms | 29 |
| 10.0.90 control | 42-44 ms | 53-61 ms | 106-118 |
| 10.0.90 with this fix | 34-38 ms | 57-61 ms | 28-47 |

The patched result returns to the 10.0.80 range. The Android Core `View`
device-test category also passes: 76 run, 74 passed, 2 ignored, 0
failed. A focused test verifies that an immediate child still
invalidates a shadow while a deeper descendant does not.

### Videos

**10.0.80 baseline**


https://github.com/user-attachments/assets/4a7e8b4a-8ebd-499b-9477-718886608ab8

**10.0.90 regression**


https://github.com/user-attachments/assets/fc2dceb7-5f1f-4eae-9461-2c53fcc6bc90

**10.0.90 with this fix**


https://github.com/user-attachments/assets/0ea77dab-5cd8-4cb5-956a-169c9b12c31b

### Issues Fixed

Fixes #37281

Regressed by #35623.
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

@kubaflo
kubaflo merged commit 7ed62a1 into release/10.0.1xx-sr10 Aug 11, 2026
1 of 10 checks passed
@kubaflo
kubaflo deleted the backport/pr-37291-to-release/10.0.1xx-sr10 branch August 11, 2026 12:20
@github-actions github-actions Bot added this to the .NET 10 SR10 milestone Aug 11, 2026
kubaflo added a commit that referenced this pull request Sep 1, 2026
…load (#37746)

<!-- Please let the below note in for people that find this PR -->
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

<!-- release-readiness-agent: human-approval-required -->
## Summary

Integrates the staged **.NET MAUI 10.0.101 (SR10.1)** payload from
`inflight/10.0.101` into `release/10.0.1xx-sr10`, based on the shipped
`10.0.100` release.

The full release inventory and servicing decisions are tracked in
#37723. The [authoritative regression
query](https://github.com/dotnet/maui/issues?q=repo%3Adotnet%2Fmaui%20is%3Aissue%20is%3Aopen%20%28label%3A%22regressed-in-10.0.10%22%20OR%20label%3A%22regressed-in-10.0.20%22%20OR%20label%3A%22regressed-in-10.0.30%22%20OR%20label%3A%22regressed-in-10.0.40%22%20OR%20label%3A%22regressed-in-10.0.50%22%20OR%20label%3A%22regressed-in-10.0.60%22%20OR%20label%3A%22regressed-in-10.0.70%22%20OR%20label%3A%22regressed-in-10.0.80%22%20OR%20label%3A%22regressed-in-10.0.90%22%20OR%20label%3A%22regressed-in-10.0.100%22%29)
remains the source for the servicing-regression scope.

> [!IMPORTANT]
> Checked items under **Staged in this PR** are merged into
`inflight/10.0.101`, not yet into `release/10.0.1xx-sr10`. They reach
the release branch only when this aggregate PR is merged.

## Status at a glance

- [x] Stage the selected regression backports independently on
`inflight/10.0.101`.
- [x] Stage the SkiaSharp 4.150.1 payload and selective
`SKPath.AddCircle` compatibility fix.
- [x] Stage the isolated iOS 26 Liquid Glass TabBar payload from #37542.
- [ ] Complete or explicitly defer the six unresolved servicing
regressions listed below.
- [ ] Complete the release gates and merge this PR into
`release/10.0.1xx-sr10`.

## Staged in this PR

### Servicing regressions

- [x] #35826 — Android MediaPicker completion from child activities.
Source #35944; component backport #37724.
- [x] #36298 — Windows dynamic `ContentPresenter` assignment. Source
#36430; component backport #37725.
- [x] #36749 — preserve custom iOS Button styling. Source #36769;
component backport #37726.
- [x] #36736 — align Android SwipeItem content. Source #36820; component
backport #37727.
- [x] #34563 — per-edge iOS safe-area handling. Source #37033; component
backport #37728.
- [x] #37706 — Android root-page back handling. Source #37709; component
backport #37729.
- [x] #37705 — Android Material 3 status-bar contrast. Source #37710;
component backport #37730.
- [x] #37423 — restore native iOS 26 Liquid Glass TabBar behavior
through the isolated four-file payload from merged PR #37542.
- [x] #37418 — Android off-screen `TranslationY` layout padding. Source
fix #37772; focused backport commit `10799e67df`.
- [x] #37361 — iOS RefreshView pull-to-refresh with an empty
CollectionView. Source fix #37404; focused backport commit `d26faa8e93`.
- [x] #37638 — Android `Screenshot.CaptureAsync` synchronous UI-thread
deadlock. Source fix #37680; focused backport commit `778040a233`.

### Planned Skia payload

- [x] Port the Skia/Svg.Skia update from #36255 through component
backport #37731.
- [x] Include only the required `SKPath.AddCircle` compatibility change
from #36787; exclude its unrelated SourceGen changes.
- [x] Confirm a matching SkiaSharp 4.150.1 native-assets/PDB build for
`_SkiaSharpNativeAssetsVersion`, or record an explicit release-owner
waiver.

### Integration follow-ups

- [x] Apply the aggregate review fixes for safe-area cache invalidation,
Activity-for-result cancellation ownership, and Android theme-test
semantics.
- [x] Keep the final branch payload as focused release commits without
unrelated `inflight/current` history.
- [x] Validate the #37418 and #37638 focused Android UI tests on the
aggregate branch (2/2 passed).
- [ ] Validate the #37361 focused iOS UI test on the aggregate branch.

## Already present on the SR10 base — no new merge needed

- [x] #36852 — Android Shell hidden-fragment leak; fix #36903 is already
in SR10.
- [x] #36735 — Android ActivityIndicator visibility; fix #36748 is
already in SR10.
- [x] #36853 — Android Shell DI-singleton route blank page; fix #36903
is already in SR10.
- [x] #36942 — Android UI event handling; fix #36988 is already in SR10.
- [x] #37281 — Android scrolling inside shadowed containers; backport
#37312 is already in SR10.

## Completed disposition — no backport required

- [x] #37700 — closed as intended SR10 `SwipeView.Threshold` behavior
from #36878; any SwipeItem sizing concern should be tracked separately.

## Not included yet — merge, defer, or explicitly disposition before
payload freeze

- [ ] #35301 — Windows CollectionView applies WinUI styling by default;
no linked fix PR.
- [ ] #34491 — Android CollectionView selection with
`PointerGestureRecognizer`; replacement fix #37952 remains draft against
`main`.
- [ ] #35059 — iOS app becomes unresponsive when opening a ComboBox
dropdown in landscape; no linked fix PR.
- [ ] #37407 — iOS TimePicker default `t` format forces en-US; fix
#37797 remains draft against `main`.
- [ ] #36269 — Android `SafeAreaEdges` with Shell tab navigation and
hidden TabBar; source fix #36474 remains open against `main` and has no
SR10 backport.
- [ ] #37657 — Android Shell/root-page `OnBackButtonPressed()` in
Release builds; no linked fix PR.

## Release completion

### Before merging this PR

- [ ] Refresh the authoritative query and reconcile #37723 with its
current results.
- [ ] Record an include/defer/close decision for every unresolved
regression above.
- [ ] Validate every included regression on its reported OS/version
using the `10.0.101` candidate packages.
- [ ] Complete current-head aggregate CI and resolve or explicitly waive
every required build/device/UI-test failure.
- [ ] Resolve or waive the Skia native-assets/PDB release gate.
- [ ] Bump `eng/Versions.props` from patch `100` to `101` after the
payload is frozen.
- [ ] Obtain the required independent current-head maintainer approvals.
- [ ] Merge #37746 into `release/10.0.1xx-sr10`.

### After merge

- [ ] Confirm BAR promotion and the per-build validation feed used by
the ship assessment.
- [ ] Publish and tag `10.0.101`.
- [ ] Complete the Visual Studio insertion/default-MAUI-version update.

## Notes

- No automated `/backport` command was used for this release payload.
- Supersedes #37745, which GitHub automatically closed when the
integration branch was renamed from `vs/10.0.101` to
`inflight/10.0.101`.
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 11, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant