[iOS][CV2] Fix page can be dragged down, and it would cause an extra space between Header and EmptyView text#31840
Conversation
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
| { | ||
| App.WaitForElement("HeaderLabel"); | ||
| App.Click("CollectionViewHeader"); | ||
| VerifyScreenshot(); |
There was a problem hiding this comment.
Pending snapshots, running a build.
There was a problem hiding this comment.
@jsuarezruiz , I have added the snapshots for all platforms
There was a problem hiding this comment.
Pull Request Overview
This PR fixes an iOS-specific issue where CollectionView's EmptyView appears with doubled Y offset when the page is dragged down, creating unwanted extra space between the Header and EmptyView.
- Changes the EmptyView positioning logic to use relative coordinates instead of absolute coordinates
- Adds comprehensive UI tests to verify the fix across platforms
- Ensures EmptyView is positioned correctly within its native container without double-offsetting
Reviewed Changes
Copilot reviewed 3 out of 7 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs | Fixed EmptyView positioning to use relative coordinates (0,0) instead of absolute frame coordinates |
| src/Controls/tests/TestCases.HostApp/Issues/Issue31465.cs | Added test page with CollectionView, Header, and EmptyView to reproduce the positioning issue |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31465.cs | Added automated UI test to verify EmptyView positioning behavior |
| TextColor = Colors.Black, | ||
| FontSize = 16, | ||
| // This binding works with string items | ||
| BindingContext = "{Binding .}" |
There was a problem hiding this comment.
The BindingContext property should not be assigned a string value. It should be assigned the actual binding expression. Use this.SetBinding(BindingContextProperty, \".\") instead, or remove this line entirely since the binding context will be set automatically for DataTemplate items.
| BindingContext = "{Binding .}" |
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
| { | ||
| _emptyViewFormsElement.Measure(frame.Width, frame.Height); | ||
| _emptyViewFormsElement.Arrange(frame.ToRectangle()); | ||
| _emptyViewFormsElement.Arrange(new Rect(0, 0, frame.Width, frame.Height)); |
There was a problem hiding this comment.
Could include a comment here?
// Arrange in the native container's local coordinate space (0,0).
// The native container (_emptyUIView) is already positioned correctly by iOS,
// so the MAUI element just needs to fill its container without additional offset.
| @@ -601,7 +601,7 @@ virtual internal CGRect LayoutEmptyView() | |||
| if (_emptyViewFormsElement != null && ((IElementController)ItemsView).LogicalChildren.IndexOf(_emptyViewFormsElement) != -1) | |||
| { | |||
| _emptyViewFormsElement.Measure(frame.Width, frame.Height); | |||
There was a problem hiding this comment.
Should validate dimensions before use it?
There was a problem hiding this comment.
@jsuarezruiz , Thanks for pointing out. I’ll add validation to ensure the width and height are greater than zero
| // Arrange in the native container's local coordinate space (0,0). | ||
| // The native container (_emptyUIView) is already positioned correctly by iOS, | ||
| // so the MAUI element just needs to fill its container without additional offset. | ||
| _emptyViewFormsElement.Arrange(new Rect(0, 0, frame.Width, frame.Height)); |
There was a problem hiding this comment.
On iOS devices with notches/home indicators, safe area insets; is correct?
There was a problem hiding this comment.
Yes @jsuarezruiz , I have ensured the fix with the latest changes on a notch screen device; it’s working fine.
Demo.mov
|
/rebase |
f304f43 to
1d95e88
Compare
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
…space between Header and EmptyView text (dotnet#31840) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details On iOS, a CollectionView with Header, EmptyView shows incorrect spacing when dragging down. The EmptyView shifts downward by double its intended Y offset leaving extra space between the header and empty view. ### Root Cause: The extra spacing happens because the header offset is applied twice. On iOS, the native container (_emptyUIView) is shifted by the ScrollView during header space calculations, and at the same time the MAUI element inside that container is also arranged with the same offset. As a result, the element ends up positioned once by its container and again by MAUI, which doubles the intended Y offset. ### Description of changes: Previously, the MAUI element was being arranged using absolute coordinates of the frame via _emptyViewFormsElement.Arrange(frame.ToRectangle()), which caused the header offset to be applied twice — once by the native container and once by the MAUI element. The fix changes the arrange call to _emptyViewFormsElement.Arrange(new Rect(0, 0, frame.Width, frame.Height)). This positions the MAUI element at the origin (0,0) within the native container while retaining its width and height. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes dotnet#31465 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **iOS**<br> <video src="https://github.com/user-attachments/assets/accebe0b-f969-43d0-8326-10de78ce2f74" width="300" height="600"> | **iOS**<br> <video src="https://github.com/user-attachments/assets/df9d7e7e-aefd-4132-95c3-5e93b815203b" width="300" height="600"> |
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [Microsoft.Maui.Controls](https://github.com/dotnet/maui) | nuget | patch | `10.0.20` -> `10.0.30` | --- ### Release Notes <details> <summary>dotnet/maui (Microsoft.Maui.Controls)</summary> ### [`v10.0.30`](https://github.com/dotnet/maui/releases/tag/10.0.30): SR3 [Compare Source](dotnet/maui@10.0.20...10.0.30) #### What's Changed .NET MAUI 10.0.30 introduces significant improvements across all platforms with focus on quality, performance, and developer experience. This release includes 106 commits with various improvements, bug fixes, and enhancements. #### .NET 10 Features - \[net10.0] Merge main to net10.0 by [@​PureWeen](https://github.com/PureWeen) in dotnet/maui#33323 #### CollectionView - Fixed the NRE in CarouselViewController on iOS 15.5 & 16.4 by [@​Ahamed-Ali](https://github.com/Ahamed-Ali) in dotnet/maui#30838 <details> <summary>🔧 Fixes</summary> - [NRE in CarouselViewController on iOS 15.5 & 16.4](dotnet/maui#28557) </details> - \[iOS, macOS] Fixed CollectionView group header size changes with ItemSizingStrategy by [@​NanthiniMahalingam](https://github.com/NanthiniMahalingam) in dotnet/maui#33161 <details> <summary>🔧 Fixes</summary> - [\[NET 10\] I6\_Grouping - Grouping_with_variable_sized_items changing the 'ItemSizingStrategy' also changes the header size.](dotnet/maui#33130) </details> - \[iOS]\[CV2] Fix page can be dragged down, and it would cause an extra space between Header and EmptyView text by [@​devanathan-vaithiyanathan](https://github.com/devanathan-vaithiyanathan) in dotnet/maui#31840 <details> <summary>🔧 Fixes</summary> - [I8\_Header_and_Footer_Null - The page can be dragged down, and it would cause an extra space between Header and EmptyView text.](dotnet/maui#31465) </details> - \[iOS] Fixed the Items not displayed properly in CarouselView2 by [@​Ahamed-Ali](https://github.com/Ahamed-Ali) in dotnet/maui#31336 <details> <summary>🔧 Fixes</summary> - [\[iOS\] Items are not updated properly in CarouselView2.](dotnet/maui#31148) </details> #### Docs - Add comprehensive README to Microsoft.Maui.Controls NuGet package by [@​jfversluis](https://github.com/jfversluis) via [@​Copilot](https://github.com/Copilot) in dotnet/maui#32835 <details> <summary>🔧 Fixes</summary> - [Improve the MAUI Nuget readme.md file](dotnet/maui#31969) </details> - Improve Controls Core API docs 2 by [@​jfversluis](https://github.com/jfversluis) in https://github.com/dotnet...
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!
Issue Details
On iOS, a CollectionView with Header, EmptyView shows incorrect spacing when dragging down. The EmptyView shifts downward by double its intended Y offset leaving extra space between the header and empty view.
Root Cause:
The extra spacing happens because the header offset is applied twice. On iOS, the native container (_emptyUIView) is shifted by the ScrollView during header space calculations, and at the same time the MAUI element inside that container is also arranged with the same offset. As a result, the element ends up positioned once by its container and again by MAUI, which doubles the intended Y offset.
Description of changes:
Previously, the MAUI element was being arranged using absolute coordinates of the frame via _emptyViewFormsElement.Arrange(frame.ToRectangle()), which caused the header offset to be applied twice — once by the native container and once by the MAUI element.
The fix changes the arrange call to _emptyViewFormsElement.Arrange(new Rect(0, 0, frame.Width, frame.Height)). This positions the MAUI element at the origin (0,0) within the native container while retaining its width and height.
Issues Fixed
Fixes #31465
Tested the behavior in the following platforms.
Before.mov
After.mov