@@ -26,6 +26,11 @@ public IView? View
26
26
27
27
bool RespondsToSafeArea ( )
28
28
{
29
+ if ( View is not ISafeAreaView sav || sav . IgnoreSafeArea )
30
+ {
31
+ return false ;
32
+ }
33
+
29
34
if ( _respondsToSafeArea . HasValue )
30
35
return _respondsToSafeArea . Value ;
31
36
return ( bool ) ( _respondsToSafeArea = RespondsToSelector ( new Selector ( "safeAreaInsets" ) ) ) ;
@@ -38,7 +43,7 @@ protected CGRect AdjustForSafeArea(CGRect bounds)
38
43
KeyboardAutoManagerScroll . ShouldScrollAgain = true ;
39
44
}
40
45
41
- if ( View is not ISafeAreaView sav || sav . IgnoreSafeArea || ! RespondsToSafeArea ( ) )
46
+ if ( ! RespondsToSafeArea ( ) )
42
47
{
43
48
return bounds ;
44
49
}
@@ -91,6 +96,12 @@ Size CrossPlatformArrange(Rect bounds)
91
96
return CrossPlatformLayout ? . CrossPlatformArrange ( bounds ) ?? Size . Zero ;
92
97
}
93
98
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.
94
105
public override CGSize SizeThatFits ( CGSize size )
95
106
{
96
107
if ( _crossPlatformLayoutReference == null )
@@ -105,6 +116,27 @@ public override CGSize SizeThatFits(CGSize size)
105
116
106
117
CacheMeasureConstraints ( widthConstraint , heightConstraint ) ;
107
118
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
+
108
140
return crossPlatformSize . ToCGSize ( ) ;
109
141
}
110
142
0 commit comments