diff --git a/api/Avalonia.nupkg.xml b/api/Avalonia.nupkg.xml
index 63f2f73cec..35d8c92717 100644
--- a/api/Avalonia.nupkg.xml
+++ b/api/Avalonia.nupkg.xml
@@ -103,6 +103,18 @@
baseline/netstandard2.0/Avalonia.Controls.dll
target/netstandard2.0/Avalonia.Controls.dll
+
+ CP0006
+ P:Avalonia.Controls.Platform.IInsetsManager.DisplayEdgeToEdgePreference
+ baseline/netstandard2.0/Avalonia.Controls.dll
+ target/netstandard2.0/Avalonia.Controls.dll
+
+
+ CP0006
+ P:Avalonia.Controls.Platform.IInsetsManager.DisplaysEdgeToEdge
+ baseline/netstandard2.0/Avalonia.Controls.dll
+ target/netstandard2.0/Avalonia.Controls.dll
+
CP0009
T:Avalonia.Diagnostics.StyleDiagnostics
diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs
index 89bccb4475..1fefe766e2 100644
--- a/samples/ControlCatalog/MainView.xaml.cs
+++ b/samples/ControlCatalog/MainView.xaml.cs
@@ -108,14 +108,14 @@ namespace ControlCatalog
ViewModel.SafeAreaPadding = insets.SafeAreaPadding;
};
- ViewModel.DisplayEdgeToEdge = insets.DisplayEdgeToEdge;
+ ViewModel.DisplayEdgeToEdge = insets.DisplayEdgeToEdgePreference;
ViewModel.IsSystemBarVisible = insets.IsSystemBarVisible ?? true;
ViewModel.PropertyChanged += async (sender, args) =>
{
if (args.PropertyName == nameof(ViewModel.DisplayEdgeToEdge))
{
- insets.DisplayEdgeToEdge = ViewModel.DisplayEdgeToEdge;
+ insets.DisplayEdgeToEdgePreference = ViewModel.DisplayEdgeToEdge;
}
else if (args.PropertyName == nameof(ViewModel.IsSystemBarVisible))
{
@@ -124,7 +124,7 @@ namespace ControlCatalog
// Give the OS some time to apply new values and refresh the view model.
await Task.Delay(100);
- ViewModel.DisplayEdgeToEdge = insets.DisplayEdgeToEdge;
+ ViewModel.DisplayEdgeToEdge = insets.DisplayEdgeToEdgePreference;
ViewModel.IsSystemBarVisible = insets.IsSystemBarVisible ?? true;
};
}
diff --git a/samples/SafeAreaDemo/ViewModels/MainViewModel.cs b/samples/SafeAreaDemo/ViewModels/MainViewModel.cs
index c52536d157..4679948a6a 100644
--- a/samples/SafeAreaDemo/ViewModels/MainViewModel.cs
+++ b/samples/SafeAreaDemo/ViewModels/MainViewModel.cs
@@ -72,7 +72,7 @@ namespace SafeAreaDemo.ViewModels
if (_insetsManager != null)
{
- _insetsManager.DisplayEdgeToEdge = value;
+ _insetsManager.DisplayEdgeToEdgePreference = value;
}
this.RaisePropertyChanged();
@@ -129,7 +129,7 @@ namespace SafeAreaDemo.ViewModels
{
_insetsManager.SafeAreaChanged += InsetsManager_SafeAreaChanged;
- _displayEdgeToEdge = _insetsManager.DisplayEdgeToEdge;
+ _displayEdgeToEdge = _insetsManager.DisplayEdgeToEdgePreference;
_hideSystemBars = !(_insetsManager.IsSystemBarVisible ?? false);
}
diff --git a/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs b/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
index 992d37ed18..2716e2057e 100644
--- a/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
+++ b/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
@@ -17,9 +17,12 @@ namespace Avalonia.Android.Platform
{
internal sealed class AndroidInsetsManager : WindowInsetsAnimationCompat.Callback, IInsetsManager, IOnApplyWindowInsetsListener, ViewTreeObserver.IOnGlobalLayoutListener, IInputPane
{
+ // For now, we check if running under net 9. TODO: remove runtime check when we target net 10
+ private static bool IsDisplayEdgeToEdgeForced = System.Environment.Version.Major >=9 && Build.VERSION.SdkInt >= (BuildVersionCodes)35;
+
private readonly Activity _activity;
private readonly TopLevelImpl _topLevel;
- private bool _displayEdgeToEdge;
+ private bool _displaysEdgeToEdge;
private bool? _systemUiVisibility;
private SystemBarTheme? _statusBarTheme;
private bool? _isDefaultSystemBarLightTheme;
@@ -27,6 +30,7 @@ namespace Avalonia.Android.Platform
private InputPaneState _state;
private Rect _previousRect;
private Insets? _previousImeInset;
+ private bool _displayEdgeToEdgePreference;
private readonly bool _usesLegacyLayouts;
private AndroidWindow Window => _activity.Window ?? throw new InvalidOperationException("Activity.Window must be set.");
@@ -50,29 +54,42 @@ namespace Avalonia.Android.Platform
}
}
- public bool DisplayEdgeToEdge
+ public bool DisplayEdgeToEdgePreference
{
- get => _displayEdgeToEdge;
+ get => _displayEdgeToEdgePreference;
set
{
- _displayEdgeToEdge = value;
+ _displayEdgeToEdgePreference = value;
- if (OperatingSystem.IsAndroidVersionAtLeast(28) && Window.Attributes is { } attributes)
- {
- attributes.LayoutInDisplayCutoutMode = value ? LayoutInDisplayCutoutMode.ShortEdges : LayoutInDisplayCutoutMode.Default;
- }
+ UpdateDisplayEdgeToEgdeState();
+ }
+ }
- WindowCompat.SetDecorFitsSystemWindows(Window, !value);
+ private void UpdateDisplayEdgeToEgdeState()
+ {
+ if (IsDisplayEdgeToEdgeForced)
+ {
+ _displaysEdgeToEdge = true;
+ return;
+ }
- if (value)
- {
- Window.AddFlags(WindowManagerFlags.TranslucentStatus);
- Window.AddFlags(WindowManagerFlags.TranslucentNavigation);
- }
- else
- {
- SystemBarColor = _systemBarColor;
- }
+ _displaysEdgeToEdge = _displayEdgeToEdgePreference;
+
+ if (OperatingSystem.IsAndroidVersionAtLeast(28) && Window.Attributes is { } attributes)
+ {
+ attributes.LayoutInDisplayCutoutMode = _displayEdgeToEdgePreference ? LayoutInDisplayCutoutMode.ShortEdges : LayoutInDisplayCutoutMode.Default;
+ }
+
+ WindowCompat.SetDecorFitsSystemWindows(Window, !_displayEdgeToEdgePreference);
+
+ if (_displayEdgeToEdgePreference)
+ {
+ Window.AddFlags(WindowManagerFlags.TranslucentStatus);
+ Window.AddFlags(WindowManagerFlags.TranslucentNavigation);
+ }
+ else
+ {
+ SystemBarColor = _systemBarColor;
}
}
@@ -89,7 +106,7 @@ namespace Avalonia.Android.Platform
_activity.Window?.DecorView.ViewTreeObserver?.AddOnGlobalLayoutListener(this);
}
- DisplayEdgeToEdge = false;
+ DisplayEdgeToEdgePreference = false;
ViewCompat.SetWindowInsetsAnimationCallback(Window.DecorView, this);
}
@@ -105,11 +122,11 @@ namespace Avalonia.Android.Platform
var renderScaling = _topLevel.RenderScaling;
var inset = insets.GetInsets(
- _displayEdgeToEdge ?
+ DisplaysEdgeToEdge ?
WindowInsetsCompat.Type.StatusBars() | WindowInsetsCompat.Type.NavigationBars() |
WindowInsetsCompat.Type.DisplayCutout() : 0);
- return new Thickness(inset.Left / renderScaling,
+ return new Thickness(inset.Left / renderScaling,
inset.Top / renderScaling,
inset.Right / renderScaling,
inset.Bottom / renderScaling);
@@ -264,7 +281,10 @@ namespace Avalonia.Android.Platform
{
_systemBarColor = value;
- if (_systemBarColor is { } color && !_displayEdgeToEdge && _activity.Window != null)
+ if (IsDisplayEdgeToEdgeForced)
+ return;
+
+ if (_systemBarColor is { } color && !_displaysEdgeToEdge && _activity.Window != null)
{
_activity.Window.ClearFlags(WindowManagerFlags.TranslucentStatus);
_activity.Window.ClearFlags(WindowManagerFlags.TranslucentNavigation);
@@ -282,6 +302,10 @@ namespace Avalonia.Android.Platform
}
}
+ public bool DisplayEdgeToEdge { get => DisplaysEdgeToEdge; set => DisplayEdgeToEdgePreference = value; }
+
+ public bool DisplaysEdgeToEdge => _displaysEdgeToEdge;
+
internal void ApplyStatusBarState()
{
IsSystemBarVisible = _systemUiVisibility;
diff --git a/src/Avalonia.Controls/Platform/IInsetsManager.cs b/src/Avalonia.Controls/Platform/IInsetsManager.cs
index 94a166a9ae..fb68e980f4 100644
--- a/src/Avalonia.Controls/Platform/IInsetsManager.cs
+++ b/src/Avalonia.Controls/Platform/IInsetsManager.cs
@@ -17,8 +17,20 @@ namespace Avalonia.Controls.Platform
///
/// Gets or sets whether the window draws edge to edge. behind any visible system bars.
///
+ bool DisplayEdgeToEdgePreference { get; set; }
+
+
+ ///
+ /// Gets or sets whether the window draws edge to edge. behind any visible system bars.
+ ///
+ [Obsolete("Use DisplayEdgeToEdgePreference")]
bool DisplayEdgeToEdge { get; set; }
+ ///
+ /// Gets whether the window is currently displaying edge to edge.
+ ///
+ bool DisplaysEdgeToEdge { get; }
+
///
/// Gets the current safe area padding.
///
@@ -39,9 +51,12 @@ namespace Avalonia.Controls.Platform
public abstract class InsetsManagerBase : IInsetsManager
{
public virtual bool? IsSystemBarVisible { get; set; }
- public virtual bool DisplayEdgeToEdge { get; set; }
+ public virtual bool DisplayEdgeToEdgePreference { get; set; }
+ public virtual bool DisplayEdgeToEdge { get => DisplaysEdgeToEdge; set => DisplayEdgeToEdgePreference = value; }
public virtual Thickness SafeAreaPadding { get; protected set; }
public virtual Color? SystemBarColor { get; set; }
+ public virtual bool DisplaysEdgeToEdge => DisplayEdgeToEdgePreference;
+
public event EventHandler? SafeAreaChanged;
protected void OnSafeAreaChanged(SafeAreaChangedArgs eventArgs)
diff --git a/src/Browser/Avalonia.Browser/BrowserInsetsManager.cs b/src/Browser/Avalonia.Browser/BrowserInsetsManager.cs
index dd34f744c1..4c042c5361 100644
--- a/src/Browser/Avalonia.Browser/BrowserInsetsManager.cs
+++ b/src/Browser/Avalonia.Browser/BrowserInsetsManager.cs
@@ -18,7 +18,7 @@ namespace Avalonia.Browser
}
}
- public override bool DisplayEdgeToEdge { get; set; }
+ public override bool DisplayEdgeToEdgePreference { get; set; }
public override Thickness SafeAreaPadding
{
diff --git a/src/iOS/Avalonia.iOS/InsetsManager.cs b/src/iOS/Avalonia.iOS/InsetsManager.cs
index 105e208ee9..170a669841 100644
--- a/src/iOS/Avalonia.iOS/InsetsManager.cs
+++ b/src/iOS/Avalonia.iOS/InsetsManager.cs
@@ -35,7 +35,7 @@ internal class InsetsManager : InsetsManagerBase
}
public event EventHandler? DisplayEdgeToEdgeChanged;
- public override bool DisplayEdgeToEdge
+ public override bool DisplayEdgeToEdgePreference
{
get => _displayEdgeToEdge;
set