Browse Source

Fix insets on android 15 (#18844)

* fix insets on android 15

* add api diff

* fix nit
pull/19036/head
Emmanuel Hansen 8 months ago
committed by GitHub
parent
commit
2dc808f3e8
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 12
      api/Avalonia.nupkg.xml
  2. 6
      samples/ControlCatalog/MainView.xaml.cs
  3. 4
      samples/SafeAreaDemo/ViewModels/MainViewModel.cs
  4. 68
      src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
  5. 17
      src/Avalonia.Controls/Platform/IInsetsManager.cs
  6. 2
      src/Browser/Avalonia.Browser/BrowserInsetsManager.cs
  7. 2
      src/iOS/Avalonia.iOS/InsetsManager.cs

12
api/Avalonia.nupkg.xml

@ -109,6 +109,18 @@
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>P:Avalonia.Controls.Platform.IInsetsManager.DisplayEdgeToEdgePreference</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>P:Avalonia.Controls.Platform.IInsetsManager.DisplaysEdgeToEdge</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0009</DiagnosticId>
<Target>T:Avalonia.Diagnostics.StyleDiagnostics</Target>

6
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;
};
}

4
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);
}

68
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;

17
src/Avalonia.Controls/Platform/IInsetsManager.cs

@ -17,8 +17,20 @@ namespace Avalonia.Controls.Platform
/// <summary>
/// Gets or sets whether the window draws edge to edge. behind any visible system bars.
/// </summary>
bool DisplayEdgeToEdgePreference { get; set; }
/// <summary>
/// Gets or sets whether the window draws edge to edge. behind any visible system bars.
/// </summary>
[Obsolete("Use DisplayEdgeToEdgePreference")]
bool DisplayEdgeToEdge { get; set; }
/// <summary>
/// Gets whether the window is currently displaying edge to edge.
/// </summary>
bool DisplaysEdgeToEdge { get; }
/// <summary>
/// Gets the current safe area padding.
/// </summary>
@ -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<SafeAreaChangedArgs>? SafeAreaChanged;
protected void OnSafeAreaChanged(SafeAreaChangedArgs eventArgs)

2
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
{

2
src/iOS/Avalonia.iOS/InsetsManager.cs

@ -35,7 +35,7 @@ internal class InsetsManager : InsetsManagerBase
}
public event EventHandler<bool>? DisplayEdgeToEdgeChanged;
public override bool DisplayEdgeToEdge
public override bool DisplayEdgeToEdgePreference
{
get => _displayEdgeToEdge;
set

Loading…
Cancel
Save