Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,11 @@ await InvokeOnMainThreadAsync(async () =>

// Wait for image to load and force the grid to measure itself again
await Task.Delay(1000);
#pragma warning disable CS0618 // Type or member is obsolete

// The layout and buttons are not connected to a window, so the measure invalidation won't propagate.
// Therefore, we have to invalidate and measure the layout manually.
layout.InvalidateMeasure();
layout.Measure(double.PositiveInfinity, double.PositiveInfinity);
#pragma warning restore CS0618 // Type or member is obsolete

await handler.ToPlatform().AssertContainsColor(Colors.Blue, MauiContext); // Grid renders
await handler.ToPlatform().AssertContainsColor(Colors.Red, MauiContext); // Image within button renders
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ public async Task LayoutPassesShouldNotIncrease()
var arrangePasses = int.Parse(match.Groups[2].Value);

#if IOS
var maxMeasurePasses = 225;
var maxArrangePasses = 247;
var maxMeasurePasses = 203;
var maxArrangePasses = 214;

if (App.FindElement("HeadingLabel").GetText() == "CollectionViewHandler2")
{
maxMeasurePasses = 380;
maxArrangePasses = 295;
maxMeasurePasses = 373;
maxArrangePasses = 276;
}
#elif ANDROID
const int maxMeasurePasses = 353;
Expand Down
51 changes: 42 additions & 9 deletions src/Core/src/Platform/iOS/MauiView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ public abstract class MauiView : UIView, ICrossPlatformLayoutBacking, IVisualTre
/// </summary>
double _lastMeasureWidth = double.NaN;

/// <summary>
/// Cached measured cross-platform size from the last measure operation tight to <see cref="_lastMeasureWidth"/> and <see cref="_lastMeasureHeight"/>.
/// Used to avoid redundant measure calls when constraints haven't changed.
/// NaN indicates no previous measure has been performed.
/// </summary>
Size? _lastMeasuredSize;

/// <summary>
/// Current safe area padding values (top, left, bottom, right) in device-independent units.
/// These values represent the insets needed to avoid system UI elements like status bars,
Expand Down Expand Up @@ -348,15 +355,34 @@ SafeAreaPadding GetAdjustedSafeAreaInsets()
/// <returns>True if the cached measure is still valid, false otherwise</returns>
protected bool IsMeasureValid(double widthConstraint, double heightConstraint)
{
return !HasFixedConstraints
&& widthConstraint == _lastMeasureWidth
return widthConstraint == _lastMeasureWidth
&& heightConstraint == _lastMeasureHeight;
}

/// <summary>
/// Caches the measure constraints and the resulting measured size from the last measure operation.
/// </summary>
/// <param name="widthConstraint">The width constraint used.</param>
/// <param name="heightConstraint">The height constraint used.</param>
[Obsolete("Use CacheMeasureConstraints(double widthConstraint, double heightConstraint, Size measuredSize) instead.")]
protected void CacheMeasureConstraints(double widthConstraint, double heightConstraint)
{
_lastMeasureWidth = widthConstraint;
_lastMeasureHeight = heightConstraint;
_lastMeasuredSize = null;
}

/// <summary>
/// Caches the measure constraints and the resulting measured size from the last measure operation.
/// </summary>
/// <param name="widthConstraint">The width constraint used.</param>
/// <param name="heightConstraint">The height constraint used.</param>
/// <param name="measuredSize">The resulting measured cross-platform size.</param>
protected void CacheMeasureConstraints(double widthConstraint, double heightConstraint, Size measuredSize)
{
_lastMeasureWidth = widthConstraint;
_lastMeasureHeight = heightConstraint;
_lastMeasuredSize = measuredSize;
}

/// <summary>
Expand All @@ -366,7 +392,7 @@ protected void CacheMeasureConstraints(double widthConstraint, double heightCons
/// <returns>True if the view has been measured, false otherwise</returns>
bool HasBeenMeasured()
{
return !double.IsNaN(_lastMeasureWidth) && !double.IsNaN(_lastMeasureHeight);
return _lastMeasuredSize.HasValue;
}

/// <summary>
Expand All @@ -378,6 +404,7 @@ protected void InvalidateConstraintsCache()
{
_lastMeasureWidth = double.NaN;
_lastMeasureHeight = double.NaN;
_lastMeasuredSize = null;
}

public ICrossPlatformLayout? CrossPlatformLayout
Expand Down Expand Up @@ -446,9 +473,14 @@ public override CGSize SizeThatFits(CGSize size)
var widthConstraint = (double)size.Width;
var heightConstraint = (double)size.Height;

var crossPlatformSize = CrossPlatformMeasure(widthConstraint, heightConstraint);
if (IsMeasureValid(widthConstraint, heightConstraint) && _lastMeasuredSize is { } crossPlatformSize)
{
return crossPlatformSize.ToCGSize();
}

crossPlatformSize = CrossPlatformMeasure(widthConstraint, heightConstraint);

CacheMeasureConstraints(widthConstraint, heightConstraint);
CacheMeasureConstraints(widthConstraint, heightConstraint, crossPlatformSize);

return crossPlatformSize.ToCGSize();
}
Expand Down Expand Up @@ -499,11 +531,12 @@ public override void LayoutSubviews()
// imposed by the parent (i.e. scroll view) with the current bounds, except when our bounds are fixed by constraints.
// But we _do_ need LayoutSubviews to make a measurement pass if the parent is something else (for example,
// the window); there's no guarantee that SizeThatFits has been called in that case.
if (!IsMeasureValid(widthConstraint, heightConstraint) && !this.IsFinalMeasureHandledBySuperView() ||
!HasBeenMeasured() && HasFixedConstraints)
var hasFixedConstraints = HasFixedConstraints;
if ((hasFixedConstraints || !IsMeasureValid(widthConstraint, heightConstraint)) && !this.IsFinalMeasureHandledBySuperView() ||
hasFixedConstraints && !HasBeenMeasured())
{
CrossPlatformMeasure(widthConstraint, heightConstraint);
CacheMeasureConstraints(widthConstraint, heightConstraint);
var crossPlatformSize = CrossPlatformMeasure(widthConstraint, heightConstraint);
CacheMeasureConstraints(widthConstraint, heightConstraint, crossPlatformSize);
}

CrossPlatformArrange(bounds);
Expand Down
1 change: 1 addition & 0 deletions src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Microsoft.Maui.Platform.MauiTimePicker.UpdateTime(System.TimeSpan? time) -> void
*REMOVED*Microsoft.Maui.Platform.MauiWebViewNavigationDelegate.DidFailNavigation(WebKit.WKWebView! webView, WebKit.WKNavigation! navigation, Foundation.NSError! error) -> void
*REMOVED*Microsoft.Maui.Platform.MauiWebViewNavigationDelegate.DidFailProvisionalNavigation(WebKit.WKWebView! webView, WebKit.WKNavigation! navigation, Foundation.NSError! error) -> void
*REMOVED*Microsoft.Maui.Platform.MauiWebViewNavigationDelegate.DidFinishNavigation(WebKit.WKWebView! webView, WebKit.WKNavigation! navigation) -> void
Microsoft.Maui.Platform.MauiView.CacheMeasureConstraints(double widthConstraint, double heightConstraint, Microsoft.Maui.Graphics.Size measuredSize) -> void
Microsoft.Maui.Platform.TextInputExtensions
Microsoft.Maui.Platform.UIApplicationExtensions
Microsoft.Maui.SafeAreaEdges
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Microsoft.Maui.Platform.MauiTimePicker.UpdateTime(System.TimeSpan? time) -> void
*REMOVED*Microsoft.Maui.Platform.MauiWebViewNavigationDelegate.DidFailNavigation(WebKit.WKWebView! webView, WebKit.WKNavigation! navigation, Foundation.NSError! error) -> void
*REMOVED*Microsoft.Maui.Platform.MauiWebViewNavigationDelegate.DidFailProvisionalNavigation(WebKit.WKWebView! webView, WebKit.WKNavigation! navigation, Foundation.NSError! error) -> void
*REMOVED*Microsoft.Maui.Platform.MauiWebViewNavigationDelegate.DidFinishNavigation(WebKit.WKWebView! webView, WebKit.WKNavigation! navigation) -> void
Microsoft.Maui.Platform.MauiView.CacheMeasureConstraints(double widthConstraint, double heightConstraint, Microsoft.Maui.Graphics.Size measuredSize) -> void
Microsoft.Maui.Platform.TextInputExtensions
Microsoft.Maui.Platform.UIApplicationExtensions
Microsoft.Maui.SafeAreaEdges
Expand Down
Loading