Skip to content

Commit

Permalink
Reapply "Fix SafeArea adjustments (#23729)" (#24600)
Browse files Browse the repository at this point in the history
This reverts commit 9522861.
  • Loading branch information
PureWeen committed Sep 5, 2024
1 parent afc1f5c commit 4317112
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<RuntimeIdentifier Condition="$(TargetFramework.Contains('-maccatalyst'))">maccatalyst-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="$(TargetFramework.Contains('-maccatalyst')) and '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)' == 'arm64'">maccatalyst-arm64</RuntimeIdentifier>
<ExcludeMicrosoftNetTestSdk>true</ExcludeMicrosoftNetTestSdk>
<RootNamespace>Maui.Controls.Sample</RootNamespace>
</PropertyGroup>

<PropertyGroup>
Expand Down
11 changes: 11 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue24246.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Issues.Issue24246"
Title="Issue24246"
xmlns:ios="clr-namespace:Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;assembly=Microsoft.Maui.Controls"
ios:Page.UseSafeArea="false">
<VerticalStackLayout Background="Purple" IgnoreSafeArea="False" VerticalOptions="Start" IsClippedToBounds="True" >
<Entry AutomationId="entry" Background="Green"></Entry>
<Label AutomationId="label" Text="If you can't interact with the above entry field, the test has failed" LineBreakMode="CharacterWrap"></Label>
</VerticalStackLayout>
</ContentPage>
11 changes: 11 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue24246.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Maui.Controls.Sample.Issues;


[Issue(IssueTracker.Github, 24246, "SafeArea arrange insets are currently insetting based on an incorrect Bounds", PlatformAffected.iOS)]
public partial class Issue24246 : ContentPage
{
public Issue24246()
{
InitializeComponent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue24246 : _IssuesUITest
{
public Issue24246(TestDevice testDevice) : base(testDevice)
{
}

public override string Issue => "SafeArea arrange insets are currently insetting based on an incorrect Bounds";

[Test]
[Category(UITestCategories.Layout)]
public void TapThenDoubleTap()
{
App.WaitForElement("entry");
App.EnterText("entry", "Hello, World!");

var result = App.WaitForElement("entry").GetText();
Assert.That(result, Is.EqualTo("Hello, World!"));
}
}
}
34 changes: 33 additions & 1 deletion src/Core/src/Platform/iOS/MauiView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,24 @@ public IView? View

bool RespondsToSafeArea()
{
if (View is not ISafeAreaView sav || sav.IgnoreSafeArea)
{
return false;
}

if (_respondsToSafeArea.HasValue)
return _respondsToSafeArea.Value;

return (bool)(_respondsToSafeArea = RespondsToSelector(new Selector("safeAreaInsets")));

}

protected CGRect AdjustForSafeArea(CGRect bounds)
{
if (KeyboardAutoManagerScroll.ShouldIgnoreSafeAreaAdjustment)
KeyboardAutoManagerScroll.ShouldScrollAgain = true;

if (View is not ISafeAreaView sav || sav.IgnoreSafeArea || !RespondsToSafeArea())
if (!RespondsToSafeArea())
{
return bounds;
}
Expand Down Expand Up @@ -88,6 +95,12 @@ Size CrossPlatformArrange(Rect bounds)
return CrossPlatformLayout?.CrossPlatformArrange(bounds) ?? Size.Zero;
}

// SizeThatFits does not take into account the constraints set on the view.
// For example, if the user has set a width and height on this view, those constraints
// will not be reflected in the value returned from this method. This method purely returns
// a measure based on the size that is passed in.
// The constraints are all applied by ViewHandlerExtensions.GetDesiredSizeFromHandler
// after it calls this method.
public override CGSize SizeThatFits(CGSize size)
{
if (_crossPlatformLayoutReference == null)
Expand All @@ -102,6 +115,25 @@ public override CGSize SizeThatFits(CGSize size)

CacheMeasureConstraints(widthConstraint, heightConstraint);

// If for some reason the upstream measure passes in a negative contraint
// Lets just bypass this code
if (RespondsToSafeArea() && widthConstraint >= 0 && heightConstraint >= 0)
{
// During the LayoutSubViews pass, we adjust the Bounds of this view for the safe area and then pass the adjusted result to CrossPlatformArrange.
// The CrossPlatformMeasure call does not include the safe area, so we need to add it here to ensure the returned size is correct.
//
// For example, if this is a layout with an Entry of height 20, CrossPlatformMeasure will return a height of 20.
// This means the bounds will be set to a height of 20, causing AdjustForSafeArea(Bounds) to return a negative bounds once it has
// subtracted the safe area insets. Therefore, we need to add the safe area insets to the CrossPlatformMeasure result to ensure correct arrangement.
var widthSafeAreaOffset = SafeAreaInsets.Left + SafeAreaInsets.Right;
var heightSafeAreaOffset = SafeAreaInsets.Top + SafeAreaInsets.Bottom;

var width = double.Clamp(crossPlatformSize.Width + widthSafeAreaOffset, 0, widthConstraint);
var height = double.Clamp(crossPlatformSize.Height + heightSafeAreaOffset, 0, heightConstraint);

return new CGSize(width, height);
}

return crossPlatformSize.ToCGSize();
}

Expand Down

0 comments on commit 4317112

Please sign in to comment.