@@ -26,6 +26,11 @@ public IView? View
2626
2727 bool RespondsToSafeArea ( )
2828 {
29+ if ( View is not ISafeAreaView sav || sav . IgnoreSafeArea )
30+ {
31+ return false ;
32+ }
33+
2934 if ( _respondsToSafeArea . HasValue )
3035 return _respondsToSafeArea . Value ;
3136 return ( bool ) ( _respondsToSafeArea = RespondsToSelector ( new Selector ( "safeAreaInsets" ) ) ) ;
@@ -38,7 +43,7 @@ protected CGRect AdjustForSafeArea(CGRect bounds)
3843 KeyboardAutoManagerScroll . ShouldScrollAgain = true ;
3944 }
4045
41- if ( View is not ISafeAreaView sav || sav . IgnoreSafeArea || ! RespondsToSafeArea ( ) )
46+ if ( ! RespondsToSafeArea ( ) )
4247 {
4348 return bounds ;
4449 }
@@ -91,6 +96,12 @@ Size CrossPlatformArrange(Rect bounds)
9196 return CrossPlatformLayout ? . CrossPlatformArrange ( bounds ) ?? Size . Zero ;
9297 }
9398
99+ // SizeThatFits does not take into account the constraints set on the view.
100+ // For example, if the user has set a width and height on this view, those constraints
101+ // will not be reflected in the value returned from this method. This method purely returns
102+ // a measure based on the size that is passed in.
103+ // The constraints are all applied by ViewHandlerExtensions.GetDesiredSizeFromHandler
104+ // after it calls this method.
94105 public override CGSize SizeThatFits ( CGSize size )
95106 {
96107 if ( _crossPlatformLayoutReference == null )
@@ -105,6 +116,27 @@ public override CGSize SizeThatFits(CGSize size)
105116
106117 CacheMeasureConstraints ( widthConstraint , heightConstraint ) ;
107118
119+ // If for some reason the upstream measure passes in a negative contraint
120+ // Lets just bypass this code
121+ if ( RespondsToSafeArea ( ) && widthConstraint >= 0 && heightConstraint >= 0 )
122+ {
123+ // During the LayoutSubViews pass, we adjust the Bounds of this view for the safe area and then pass the adjusted result to CrossPlatformArrange.
124+ // The CrossPlatformMeasure call does not include the safe area, so we need to add it here to ensure the returned size is correct.
125+ //
126+ // For example, if this is a layout with an Entry of height 20, CrossPlatformMeasure will return a height of 20.
127+ // This means the bounds will be set to a height of 20, causing AdjustForSafeArea(Bounds) to return a negative bounds once it has
128+ // subtracted the safe area insets. Therefore, we need to add the safe area insets to the CrossPlatformMeasure result to ensure correct arrangement.
129+ var widthSafeAreaOffset = SafeAreaInsets . Left + SafeAreaInsets . Right ;
130+ var heightSafeAreaOffset = SafeAreaInsets . Top + SafeAreaInsets . Bottom ;
131+
132+ CacheMeasureConstraints ( widthConstraint + widthSafeAreaOffset , heightConstraint + heightSafeAreaOffset ) ;
133+
134+ var width = double . Clamp ( crossPlatformSize . Width + widthSafeAreaOffset , 0 , widthConstraint ) ;
135+ var height = double . Clamp ( crossPlatformSize . Height + heightSafeAreaOffset , 0 , heightConstraint ) ;
136+
137+ return new CGSize ( width , height ) ;
138+ }
139+
108140 return crossPlatformSize . ToCGSize ( ) ;
109141 }
110142
0 commit comments