diff --git a/src/Controls/src/Core/Border/Border.cs b/src/Controls/src/Core/Border/Border.cs
index b7f6b5804cfa..8b9e77ca26e5 100644
--- a/src/Controls/src/Core/Border/Border.cs
+++ b/src/Controls/src/Core/Border/Border.cs
@@ -357,6 +357,12 @@ SafeAreaRegions ISafeAreaView2.GetSafeAreaRegionsForEdge(int edge)
// Use direct property
var regionForEdge = SafeAreaEdges.GetEdge(edge);
+ if (regionForEdge == SafeAreaRegions.Default)
+ {
+ // If no safe area edges are set, return None
+ return SafeAreaRegions.None;
+ }
+
// For Border, return as-is
return regionForEdge;
}
diff --git a/src/Controls/src/Core/ContentView/ContentView.cs b/src/Controls/src/Core/ContentView/ContentView.cs
index 7438c52d60cb..89c1b7ef31e6 100644
--- a/src/Controls/src/Core/ContentView/ContentView.cs
+++ b/src/Controls/src/Core/ContentView/ContentView.cs
@@ -88,6 +88,12 @@ SafeAreaRegions ISafeAreaView2.GetSafeAreaRegionsForEdge(int edge)
// Use direct property
var regionForEdge = SafeAreaEdges.GetEdge(edge);
+ if (regionForEdge == SafeAreaRegions.Default)
+ {
+ // If no safe area edges are set, return None
+ return SafeAreaRegions.None;
+ }
+
// For ContentView, return the region directly
return regionForEdge;
}
diff --git a/src/Controls/src/Core/Page/Page.cs b/src/Controls/src/Core/Page/Page.cs
index be8b94dccbd8..c2f35f7f082b 100644
--- a/src/Controls/src/Core/Page/Page.cs
+++ b/src/Controls/src/Core/Page/Page.cs
@@ -265,11 +265,15 @@ Thickness ISafeAreaView2.SafeAreaInsets
///
SafeAreaRegions ISafeAreaView2.GetSafeAreaRegionsForEdge(int edge)
{
- // Use new SafeAreaElement method
- var regionForEdge = SafeAreaElement.GetEdgeValue(this, edge);
-
- // For Page (but not ContentPage), return as-is
- return regionForEdge;
+ var ignoreSafeArea = ((ISafeAreaView)this).IgnoreSafeArea;
+ if (ignoreSafeArea)
+ {
+ return SafeAreaRegions.None; // If legacy says "ignore", return None (edge-to-edge)
+ }
+ else
+ {
+ return SafeAreaRegions.Container; // If legacy says "don't ignore", return Container
+ }
}
///
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue28986_Border.xaml b/src/Controls/tests/TestCases.HostApp/Issues/Issue28986_Border.xaml
index 158e187d1403..9e089fb3b942 100644
--- a/src/Controls/tests/TestCases.HostApp/Issues/Issue28986_Border.xaml
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue28986_Border.xaml
@@ -3,156 +3,190 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Issues.Issue28986_Border"
Title="SafeArea Border Test">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- None
- SoftInput
- Container
- Default
- All
-
-
-
-
-
-
-
-
-
- None
- SoftInput
- Container
- Default
- All
-
-
-
-
-
-
-
-
- None
- SoftInput
- Container
- Default
- All
-
-
-
-
-
-
-
-
-
- None
- SoftInput
- Container
- Default
- All
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ None
+ SoftInput
+ Container
+ Default
+ All
+
+
+
+
+
+
+
+
+
+ None
+ SoftInput
+ Container
+ Default
+ All
+
+
+
+
+
+
+
+
+ None
+ SoftInput
+ Container
+ Default
+ All
+
+
+
+
+
+
+
+
+
+ None
+ SoftInput
+ Container
+ Default
+ All
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue28986_ContentView.xaml b/src/Controls/tests/TestCases.HostApp/Issues/Issue28986_ContentView.xaml
index 8a772d7312c8..ae03725b9c44 100644
--- a/src/Controls/tests/TestCases.HostApp/Issues/Issue28986_ContentView.xaml
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue28986_ContentView.xaml
@@ -3,155 +3,186 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Issues.Issue28986_ContentView"
Title="SafeArea ContentView Test">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- None
- SoftInput
- Container
- Default
- All
-
-
-
-
-
-
-
-
-
- None
- SoftInput
- Container
- Default
- All
-
-
-
-
-
-
-
-
- None
- SoftInput
- Container
- Default
- All
-
-
-
-
-
-
-
-
-
- None
- SoftInput
- Container
- Default
- All
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ None
+ SoftInput
+ Container
+ Default
+ All
+
+
+
+
+
+
+
+
+
+ None
+ SoftInput
+ Container
+ Default
+ All
+
+
+
+
+
+
+
+
+ None
+ SoftInput
+ Container
+ Default
+ All
+
+
+
+
+
+
+
+
+
+ None
+ SoftInput
+ Container
+ Default
+ All
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28986_Border.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28986_Border.cs
new file mode 100644
index 000000000000..58b619170c4c
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28986_Border.cs
@@ -0,0 +1,49 @@
+#if IOS
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues
+{
+ public class Issue28986_Border : _IssuesUITest
+ {
+ public override string Issue => "Test SafeArea Border for per-edge safe area control";
+
+ public Issue28986_Border(TestDevice device) : base(device)
+ {
+ }
+
+ [Test]
+ [Category(UITestCategories.Border)]
+ public void SafeAreaBorderBasicFunctionality()
+ {
+ var borderContent = App.WaitForElement("BorderContent");
+
+ // 1. Ensure SafeAreaEdges is Default
+ var initialSettings = App.FindElement("CurrentSettings").GetText();
+ Assert.That(initialSettings, Does.Contain("Left: Default, Top: Default, Right: Default, Bottom: Default"));
+ var borderWithDefaultSettings = borderContent.GetRect();
+ // Verify that Border starts at Y=5 when SafeAreaEdges is Default
+ // Because the border stroke thickness is 5
+ Assert.That(borderWithDefaultSettings.Y, Is.EqualTo(5), "Border should start at Y=5 when SafeAreaEdges is set to Default");
+
+ // 2. Ensure SafeAreaEdges are set to All
+ App.Tap("ResetAllButton");
+ var allSettings = App.FindElement("CurrentSettings").GetText();
+ Assert.That(allSettings, Does.Contain("Left: All, Top: All, Right: All, Bottom: All"));
+ var borderSafeAreaEdgesAll = App.WaitForElement("BorderContent").GetRect();
+ Assert.That(borderSafeAreaEdgesAll.Y, Is.GreaterThan(borderWithDefaultSettings.Y), "Border should move down (greater Y position) when SafeAreaEdges changes from Default to All");
+
+ // 3. Ensure SafeAreaEdges are set to None (edge-to-edge)
+ App.Tap("ResetNoneButton");
+ var noneSettings = App.FindElement("CurrentSettings").GetText();
+ Assert.That(noneSettings, Does.Contain("Left: None, Top: None, Right: None, Bottom: None"));
+ var borderSafeAreaEdgesNone = App.WaitForElement("BorderContent").GetRect();
+ // Verify that Border position is at Y=5 when SafeAreaEdges is None
+ // This is because the border stroke thickness is 5
+ Assert.That(borderSafeAreaEdgesNone.Y, Is.EqualTo(5),
+ "Border should be at Y=5 when SafeAreaEdges is set to None (edge-to-edge)");
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28986_ContentView.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28986_ContentView.cs
new file mode 100644
index 000000000000..aa0acb2a3012
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28986_ContentView.cs
@@ -0,0 +1,49 @@
+#if IOS
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues
+{
+ public class Issue28986_ContentView : _IssuesUITest
+ {
+ public override string Issue => "Test SafeArea ContentView for per-edge safe area control";
+
+ public Issue28986_ContentView(TestDevice device) : base(device)
+ {
+ }
+
+ [Test]
+ [Category(UITestCategories.Layout)]
+ public void SafeAreaContentViewBasicFunctionality()
+ {
+ var contentViewContent = App.WaitForElement("ContentViewContent");
+
+ // 1. Ensure SafeAreaEdges is Default
+ var initialSettings = App.FindElement("CurrentSettings").GetText();
+ Assert.That(initialSettings, Does.Contain("Left: Default, Top: Default, Right: Default, Bottom: Default"));
+ var contentViewWithDefaultSettings = contentViewContent.GetRect();
+ // Verify that ContentView content starts at Y=0 when SafeAreaEdges is Default
+ Assert.That(contentViewWithDefaultSettings.Y, Is.EqualTo(0),
+ "ContentView should start at Y=0 when SafeAreaEdges is set to Default");
+
+ // 2. Ensure SafeAreaEdges are set to All
+ App.Tap("ResetAllButton");
+ var allSettings = App.FindElement("CurrentSettings").GetText();
+ Assert.That(allSettings, Does.Contain("Left: All, Top: All, Right: All, Bottom: All"));
+ var contentViewSafeAreaEdgesAll = App.WaitForElement("ContentViewContent").GetRect();
+ Assert.That(contentViewSafeAreaEdgesAll.Y, Is.GreaterThan(contentViewWithDefaultSettings.Y),
+ "ContentView should move down (greater Y position) when SafeAreaEdges changes from Default to All");
+
+ // 3. Ensure SafeAreaEdges are set to None (edge-to-edge)
+ App.Tap("ResetNoneButton");
+ var noneSettings = App.FindElement("CurrentSettings").GetText();
+ Assert.That(noneSettings, Does.Contain("Left: None, Top: None, Right: None, Bottom: None"));
+ var contentViewSafeAreaEdgesNone = App.WaitForElement("ContentViewContent").GetRect();
+ // Verify that ContentView position is at Y=0 when SafeAreaEdges is None
+ Assert.That(contentViewSafeAreaEdgesNone.Y, Is.EqualTo(0),
+ "ContentView should be at Y=0 when SafeAreaEdges is set to None (edge-to-edge)");
+ }
+ }
+}
+#endif
\ No newline at end of file