@@ -26,9 +26,16 @@ 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 ;
36
+
31
37
return ( bool ) ( _respondsToSafeArea = RespondsToSelector ( new Selector ( "safeAreaInsets" ) ) ) ;
38
+
32
39
}
33
40
34
41
protected CGRect AdjustForSafeArea ( CGRect bounds )
@@ -38,7 +45,7 @@ protected CGRect AdjustForSafeArea(CGRect bounds)
38
45
KeyboardAutoManagerScroll . ShouldScrollAgain = true ;
39
46
}
40
47
41
- if ( View is not ISafeAreaView sav || sav . IgnoreSafeArea || ! RespondsToSafeArea ( ) )
48
+ if ( ! RespondsToSafeArea ( ) )
42
49
{
43
50
return bounds ;
44
51
}
@@ -91,6 +98,12 @@ Size CrossPlatformArrange(Rect bounds)
91
98
return CrossPlatformLayout ? . CrossPlatformArrange ( bounds ) ?? Size . Zero ;
92
99
}
93
100
101
+ // SizeThatFits does not take into account the constraints set on the view.
102
+ // For example, if the user has set a width and height on this view, those constraints
103
+ // will not be reflected in the value returned from this method. This method purely returns
104
+ // a measure based on the size that is passed in.
105
+ // The constraints are all applied by ViewHandlerExtensions.GetDesiredSizeFromHandler
106
+ // after it calls this method.
94
107
public override CGSize SizeThatFits ( CGSize size )
95
108
{
96
109
if ( _crossPlatformLayoutReference == null )
@@ -105,6 +118,25 @@ public override CGSize SizeThatFits(CGSize size)
105
118
106
119
CacheMeasureConstraints ( widthConstraint , heightConstraint ) ;
107
120
121
+ // If for some reason the upstream measure passes in a negative contraint
122
+ // Lets just bypass this code
123
+ if ( RespondsToSafeArea ( ) && widthConstraint >= 0 && heightConstraint >= 0 )
124
+ {
125
+ // During the LayoutSubViews pass, we adjust the Bounds of this view for the safe area and then pass the adjusted result to CrossPlatformArrange.
126
+ // The CrossPlatformMeasure call does not include the safe area, so we need to add it here to ensure the returned size is correct.
127
+ //
128
+ // For example, if this is a layout with an Entry of height 20, CrossPlatformMeasure will return a height of 20.
129
+ // This means the bounds will be set to a height of 20, causing AdjustForSafeArea(Bounds) to return a negative bounds once it has
130
+ // subtracted the safe area insets. Therefore, we need to add the safe area insets to the CrossPlatformMeasure result to ensure correct arrangement.
131
+ var widthSafeAreaOffset = SafeAreaInsets . Left + SafeAreaInsets . Right ;
132
+ var heightSafeAreaOffset = SafeAreaInsets . Top + SafeAreaInsets . Bottom ;
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