Skip to content

Commit c4d4f3f

Browse files
praveenkumarkarunanithisheiksyedm
authored andcommitted
code revert and test update
1 parent ac6e7d5 commit c4d4f3f

File tree

2 files changed

+74
-37
lines changed

2 files changed

+74
-37
lines changed

src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.iOS.cs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,5 +319,77 @@ Rect GetCollectionViewCellBounds(IView cellContent)
319319

320320
return cellContent.ToPlatform().GetParentOfType<UIKit.UICollectionViewCell>().GetBoundingBox();
321321
}
322+
323+
// Regression test for https://github.com/dotnet/maui/issues/34635
324+
// PR #33908 changed RespondsToSafeArea() to exclude UICollectionView from the
325+
// UIScrollView descendant check, allowing CV cell content views to respond to
326+
// safe area. This caused Window.SafeAreaInsets (title bar ~41px on macOS) to be
327+
// applied to every cell, shifting content by 41px.
328+
// The fix ensures CV cell content views are treated as UIScrollView descendants
329+
// (since UICollectionView inherits from UIScrollView), so they do NOT respond
330+
// to safe area independently.
331+
[Fact("https://github.com/dotnet/maui/issues/34635")]
332+
[Category(TestCategory.CollectionView)]
333+
public async Task CollectionViewCellContentShouldBeScrollViewDescendant()
334+
{
335+
SetupBuilder();
336+
337+
var collectionView = new CollectionView
338+
{
339+
ItemsSource = Enumerable.Range(0, 5).Select(i => $"Item {i}").ToList(),
340+
ItemTemplate = new DataTemplate(() =>
341+
{
342+
var grid = new Grid { Padding = new Thickness(10) };
343+
var label = new Label();
344+
label.SetBinding(Label.TextProperty, ".");
345+
grid.Add(label);
346+
return grid;
347+
}),
348+
};
349+
350+
await CreateHandlerAndAddToWindow<CollectionViewHandler>(collectionView, async handler =>
351+
{
352+
await Task.Delay(500);
353+
354+
var platformCV = collectionView.ToPlatform();
355+
Assert.NotNull(platformCV);
356+
357+
var uiCollectionView = platformCV as UICollectionView
358+
?? platformCV.GetParentOfType<UICollectionView>();
359+
360+
if (uiCollectionView is null && platformCV is UIView pv)
361+
uiCollectionView = pv.Subviews.OfType<UICollectionView>().FirstOrDefault();
362+
363+
Assert.NotNull(uiCollectionView);
364+
365+
var visibleCells = uiCollectionView.VisibleCells;
366+
Assert.NotEmpty(visibleCells);
367+
368+
foreach (var cell in visibleCells)
369+
{
370+
foreach (var mv in FindAllSubviews<MauiView>(cell))
371+
{
372+
mv.SetNeedsLayout();
373+
mv.LayoutIfNeeded();
374+
375+
Assert.False(mv.AppliesSafeAreaAdjustments,
376+
$"CollectionView cell MauiView '{mv.View?.GetType().Name}' should not apply safe area adjustments. " +
377+
"Cell views inside UICollectionView must be treated as scroll view descendants.");
378+
}
379+
}
380+
});
381+
}
382+
383+
static List<T> FindAllSubviews<T>(UIView root) where T : UIView
384+
{
385+
var result = new List<T>();
386+
foreach (var subview in root.Subviews)
387+
{
388+
if (subview is T match)
389+
result.Add(match);
390+
result.AddRange(FindAllSubviews<T>(subview));
391+
}
392+
return result;
393+
}
322394
}
323395
}

src/Core/src/Platform/iOS/MauiView.cs

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,6 @@ public abstract class MauiView : UIView, ICrossPlatformLayoutBacking, IVisualTre
7272
// Null means not yet determined. Invalidated when view hierarchy changes.
7373
bool? _parentHandlesSafeArea;
7474

75-
// Cached UICollectionView parent detection to avoid repeated hierarchy checks.
76-
bool? _collectionViewDescendant;
77-
78-
// Cached Window safe area padding for CollectionView children to detect changes.
79-
// Uses SafeAreaPadding with EqualsAtPixelLevel() to absorb sub-pixel animation noise.
80-
SafeAreaPadding _lastWindowSafeAreaPadding;
81-
8275
// Keyboard tracking
8376
CGRect _keyboardFrame = CGRect.Empty;
8477
bool _isKeyboardShowing;
@@ -132,18 +125,9 @@ bool RespondsToSafeArea()
132125
// To prevent this, we ignore safe area calculations on child views when they are inside a scroll view.
133126
// The scrollview itself is responsible for applying the correct insets, and child views should not apply additional safe area logic.
134127
//
135-
// EXCEPTION: CollectionView items must handle their own safe area because UICollectionView (which inherits from UIScrollView)
136-
// does not automatically apply safe area insets to individual cells. Without this exception, CollectionView content
137-
// would render under the notch and home indicator.
138-
//
139128
// For more details and implementation specifics, see MauiScrollView.cs, which contains the logic for safe area management
140129
// within scroll views and explains how this interacts with the overall layout system.
141-
var scrollViewParent = this.GetParentOfType<UIScrollView>();
142-
_scrollViewDescendant = scrollViewParent is not null && scrollViewParent is not UICollectionView;
143-
144-
// Cache whether this view is inside a UICollectionView for use in CrossPlatformArrange()
145-
_collectionViewDescendant = scrollViewParent is UICollectionView;
146-
130+
_scrollViewDescendant = this.GetParentOfType<UIScrollView>() is not null;
147131
return !_scrollViewDescendant.Value;
148132
}
149133

@@ -310,12 +294,7 @@ void OnKeyboardWillHide(NSNotification notification)
310294

311295
SafeAreaPadding GetAdjustedSafeAreaInsets()
312296
{
313-
// CollectionView cells don't receive SafeAreaInsetsDidChange notifications, so their SafeAreaInsets
314-
// property may be stale during layout (especially after rotation). Use Window.SafeAreaInsets instead,
315-
// which always reflects the current device orientation and safe area state.
316-
var baseSafeArea = _collectionViewDescendant == true && Window is not null
317-
? Window.SafeAreaInsets.ToSafeAreaInsets()
318-
: SafeAreaInsets.ToSafeAreaInsets();
297+
var baseSafeArea = SafeAreaInsets.ToSafeAreaInsets();
319298

320299
// Check if keyboard-aware safe area adjustments are needed
321300
if (View is ISafeAreaView2 safeAreaPage && _isKeyboardShowing)
@@ -545,18 +524,6 @@ Size CrossPlatformMeasure(double widthConstraint, double heightConstraint)
545524
/// <param name="bounds">The bounds rectangle to arrange within</param>
546525
void CrossPlatformArrange(CGRect bounds)
547526
{
548-
// Force safe area revalidation for CollectionView cells when Window safe area changes.
549-
if (View is ISafeAreaView or ISafeAreaView2 && _collectionViewDescendant == true && Window is not null)
550-
{
551-
var currentWindowPadding = Window.SafeAreaInsets.ToSafeAreaInsets();
552-
if (!currentWindowPadding.EqualsAtPixelLevel(_lastWindowSafeAreaPadding))
553-
{
554-
_lastWindowSafeAreaPadding = currentWindowPadding;
555-
_safeAreaInvalidated = true;
556-
ValidateSafeArea();
557-
}
558-
}
559-
560527
if (_appliesSafeAreaAdjustments)
561528
{
562529
bounds = AdjustForSafeArea(bounds);
@@ -801,8 +768,6 @@ public override void MovedToWindow()
801768

802769
_scrollViewDescendant = null;
803770
_parentHandlesSafeArea = null;
804-
_collectionViewDescendant = null;
805-
_lastWindowSafeAreaPadding = SafeAreaPadding.Empty;
806771

807772
// Notify any subscribers that this view has been moved to a window
808773
_movedToWindow?.Invoke(this, EventArgs.Empty);

0 commit comments

Comments
 (0)