Browse Source

add system bar color attached property

pull/10802/head
Emmanuel Hansen 3 years ago
parent
commit
7c460a9bcb
  1. 2
      samples/ControlCatalog.Android/MainActivity.cs
  2. 4
      samples/ControlCatalog.Android/Resources/values-night/colors.xml
  3. 4
      src/Android/Avalonia.Android/AvaloniaMainActivity.cs
  4. 43
      src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
  5. 13
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  6. 8
      src/Avalonia.Controls/Platform/IInsetsManager.cs
  7. 46
      src/Avalonia.Controls/TopLevel.cs
  8. 1
      src/Avalonia.Themes.Fluent/Controls/EmbeddableControlRoot.xaml
  9. 1
      src/Avalonia.Themes.Fluent/Controls/Window.xaml
  10. 3
      src/Browser/Avalonia.Browser/BrowserInsetsManager.cs
  11. 3
      src/iOS/Avalonia.iOS/InsetsManager.cs

2
samples/ControlCatalog.Android/MainActivity.cs

@ -5,7 +5,7 @@ using Avalonia.Android;
namespace ControlCatalog.Android namespace ControlCatalog.Android
{ {
[Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.Main", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] [Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.Main", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
public class MainActivity : AvaloniaMainActivity public class MainActivity : AvaloniaMainActivity
{ {
} }

4
samples/ControlCatalog.Android/Resources/values-night/colors.xml

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="splash_background">#212121</color>
</resources>

4
src/Android/Avalonia.Android/AvaloniaMainActivity.cs

@ -32,10 +32,6 @@ namespace Avalonia.Android
{ {
lifetime.View = View; lifetime.View = View;
} }
Window?.ClearFlags(WindowManagerFlags.TranslucentStatus);
Window?.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
base.OnCreate(savedInstanceState); base.OnCreate(savedInstanceState);
SetContentView(View); SetContentView(View);

43
src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs

@ -2,11 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using Android.OS; using Android.OS;
using Android.Views; using Android.Views;
using AndroidX.AppCompat.App;
using AndroidX.Core.View; using AndroidX.Core.View;
using Avalonia.Android.Platform.SkiaPlatform; using Avalonia.Android.Platform.SkiaPlatform;
using Avalonia.Controls.Platform; using Avalonia.Controls.Platform;
using static Avalonia.Controls.Platform.IInsetsManager; using Avalonia.Media;
namespace Avalonia.Android.Platform namespace Avalonia.Android.Platform
{ {
@ -20,6 +19,7 @@ namespace Avalonia.Android.Platform
private bool? _systemUiVisibility; private bool? _systemUiVisibility;
private SystemBarTheme? _statusBarTheme; private SystemBarTheme? _statusBarTheme;
private bool? _isDefaultSystemBarLightTheme; private bool? _isDefaultSystemBarLightTheme;
private Color? _systemBarColor;
public event EventHandler<SafeAreaChangedArgs> SafeAreaChanged; public event EventHandler<SafeAreaChangedArgs> SafeAreaChanged;
@ -36,6 +36,16 @@ namespace Avalonia.Android.Platform
} }
WindowCompat.SetDecorFitsSystemWindows(_activity.Window, !value); WindowCompat.SetDecorFitsSystemWindows(_activity.Window, !value);
if(value)
{
_activity.Window.AddFlags(WindowManagerFlags.TranslucentStatus);
_activity.Window.AddFlags(WindowManagerFlags.TranslucentNavigation);
}
else
{
SystemBarColor = _systemBarColor;
}
} }
} }
@ -93,6 +103,7 @@ namespace Avalonia.Android.Platform
public WindowInsetsCompat OnApplyWindowInsets(View v, WindowInsetsCompat insets) public WindowInsetsCompat OnApplyWindowInsets(View v, WindowInsetsCompat insets)
{ {
NotifySafeAreaChanged(SafeAreaPadding); NotifySafeAreaChanged(SafeAreaPadding);
insets = ViewCompat.OnApplyWindowInsets(v, insets);
return insets; return insets;
} }
@ -146,8 +157,6 @@ namespace Avalonia.Android.Platform
compat.AppearanceLightStatusBars = value == Controls.Platform.SystemBarTheme.Light; compat.AppearanceLightStatusBars = value == Controls.Platform.SystemBarTheme.Light;
compat.AppearanceLightNavigationBars = value == Controls.Platform.SystemBarTheme.Light; compat.AppearanceLightNavigationBars = value == Controls.Platform.SystemBarTheme.Light;
AppCompatDelegate.DefaultNightMode = isDefault ? AppCompatDelegate.ModeNightFollowSystem : compat.AppearanceLightStatusBars ? AppCompatDelegate.ModeNightNo : AppCompatDelegate.ModeNightYes;
} }
} }
@ -190,10 +199,36 @@ namespace Avalonia.Android.Platform
} }
} }
public Color? SystemBarColor
{
get => _systemBarColor;
set
{
_systemBarColor = value;
if (_systemBarColor is { } color && !_displayEdgeToEdge && _activity.Window != null)
{
_activity.Window.ClearFlags(WindowManagerFlags.TranslucentStatus);
_activity.Window.ClearFlags(WindowManagerFlags.TranslucentNavigation);
_activity.Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
var androidColor = global::Android.Graphics.Color.Argb(color.A, color.R, color.G, color.B);
_activity.Window.SetStatusBarColor(androidColor);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
// As we can only change the navigation bar's foreground api 26 and newer, we only change the background color if running on those versions
_activity.Window.SetNavigationBarColor(androidColor);
}
}
}
}
internal void ApplyStatusBarState() internal void ApplyStatusBarState()
{ {
IsSystemBarVisible = _systemUiVisibility; IsSystemBarVisible = _systemUiVisibility;
SystemBarTheme = _statusBarTheme; SystemBarTheme = _statusBarTheme;
SystemBarColor = _systemBarColor;
} }
private class InsetsAnimationCallback : WindowInsetsAnimationCompat.Callback private class InsetsAnimationCallback : WindowInsetsAnimationCompat.Callback

13
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -3,9 +3,13 @@ using System.Collections.Generic;
using Android.App; using Android.App;
using Android.Content; using Android.Content;
using Android.Graphics; using Android.Graphics;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Runtime; using Android.Runtime;
using Android.Text;
using Android.Views; using Android.Views;
using Android.Views.InputMethods; using Android.Views.InputMethods;
using AndroidX.AppCompat.App;
using Avalonia.Android.Platform.Specific; using Avalonia.Android.Platform.Specific;
using Avalonia.Android.Platform.Specific.Helpers; using Avalonia.Android.Platform.Specific.Helpers;
using Avalonia.Android.Platform.Storage; using Avalonia.Android.Platform.Storage;
@ -22,13 +26,6 @@ using Avalonia.Platform.Storage;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.Rendering.Composition; using Avalonia.Rendering.Composition;
using Java.Lang; using Java.Lang;
using Java.Util;
using Math = System.Math;
using AndroidRect = Android.Graphics.Rect;
using Window = Android.Views.Window;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Text;
namespace Avalonia.Android.Platform.SkiaPlatform namespace Avalonia.Android.Platform.SkiaPlatform
{ {
@ -286,6 +283,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform
_ => null, _ => null,
}; };
} }
AppCompatDelegate.DefaultNightMode = themeVariant == PlatformThemeVariant.Light ? AppCompatDelegate.ModeNightNo : AppCompatDelegate.ModeNightYes;
} }
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels => new AcrylicPlatformCompensationLevels(1, 1, 1); public AcrylicPlatformCompensationLevels AcrylicCompensationLevels => new AcrylicPlatformCompensationLevels(1, 1, 1);

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

@ -1,4 +1,5 @@
using System; using System;
using Avalonia.Media;
using Avalonia.Metadata; using Avalonia.Metadata;
#nullable enable #nullable enable
@ -22,7 +23,12 @@ namespace Avalonia.Controls.Platform
/// Gets the current safe area padding. /// Gets the current safe area padding.
/// </summary> /// </summary>
Thickness SafeAreaPadding { get; } Thickness SafeAreaPadding { get; }
/// <summary>
/// Gets or sets the color of the platform's system bars
/// </summary>
Color? SystemBarColor { get; set; }
/// <summary> /// <summary>
/// Occurs when safe area for the current window changes. /// Occurs when safe area for the current window changes.
/// </summary> /// </summary>

46
src/Avalonia.Controls/TopLevel.cs

@ -87,7 +87,15 @@ namespace Avalonia.Controls
/// <inheritdoc cref="ThemeVariantScope.RequestedThemeVariantProperty" /> /// <inheritdoc cref="ThemeVariantScope.RequestedThemeVariantProperty" />
public static readonly StyledProperty<ThemeVariant?> RequestedThemeVariantProperty = public static readonly StyledProperty<ThemeVariant?> RequestedThemeVariantProperty =
ThemeVariantScope.RequestedThemeVariantProperty.AddOwner<Application>(); ThemeVariantScope.RequestedThemeVariantProperty.AddOwner<Application>();
/// <summary>
/// Defines the SystemBarColor attached property.
/// </summary>
public static readonly AttachedProperty<SolidColorBrush?> SystemBarColorProperty =
AvaloniaProperty.RegisterAttached<TopLevel, Control, SolidColorBrush?>(
"SystemBarColor",
inherits: true);
/// <summary> /// <summary>
/// Defines the <see cref="BackRequested"/> event. /// Defines the <see cref="BackRequested"/> event.
/// </summary> /// </summary>
@ -124,6 +132,22 @@ namespace Avalonia.Controls
{ {
KeyboardNavigation.TabNavigationProperty.OverrideDefaultValue<TopLevel>(KeyboardNavigationMode.Cycle); KeyboardNavigation.TabNavigationProperty.OverrideDefaultValue<TopLevel>(KeyboardNavigationMode.Cycle);
AffectsMeasure<TopLevel>(ClientSizeProperty); AffectsMeasure<TopLevel>(ClientSizeProperty);
SystemBarColorProperty.Changed.AddClassHandler<Control>((view, e) =>
{
if (e.NewValue is SolidColorBrush colorBrush)
{
if (view.Parent is TopLevel tl && tl.InsetsManager is { } insetsManager)
{
insetsManager.SystemBarColor = colorBrush.Color;
}
if (view is TopLevel topLevel && topLevel.InsetsManager is { } insets)
{
insets.SystemBarColor = colorBrush.Color;
}
}
});
} }
/// <summary> /// <summary>
@ -379,6 +403,26 @@ namespace Avalonia.Controls
set { SetValue(AccessText.ShowAccessKeyProperty, value); } set { SetValue(AccessText.ShowAccessKeyProperty, value); }
} }
/// <summary>
/// Helper for setting the color of the platform's system bars
/// </summary>
/// <param name="control">The main view attached to the toplevel, or the toplevel</param>
/// <param name="color">The color to set</param>
public static void SetSystemBarColor(Control control, SolidColorBrush? color)
{
control.SetValue(SystemBarColorProperty, color);
}
/// <summary>
/// Helper for getting the color of the platform's system bars
/// </summary>
/// <param name="control">The main view attached to the toplevel, or the toplevel</param>
/// <returns>The current color of the platform's system bars</returns>
public static SolidColorBrush? GetSystemBarColor(Control control)
{
return control.GetValue(SystemBarColorProperty);
}
/// <inheritdoc/> /// <inheritdoc/>
double ILayoutRoot.LayoutScaling => PlatformImpl?.RenderScaling ?? 1; double ILayoutRoot.LayoutScaling => PlatformImpl?.RenderScaling ?? 1;

1
src/Avalonia.Themes.Fluent/Controls/EmbeddableControlRoot.xaml

@ -3,6 +3,7 @@
<ControlTheme x:Key="{x:Type EmbeddableControlRoot}" TargetType="EmbeddableControlRoot"> <ControlTheme x:Key="{x:Type EmbeddableControlRoot}" TargetType="EmbeddableControlRoot">
<Setter Property="Foreground" Value="{DynamicResource SystemControlForegroundBaseHighBrush}"/> <Setter Property="Foreground" Value="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
<Setter Property="Background" Value="{DynamicResource SystemControlBackgroundAltHighBrush}"/> <Setter Property="Background" Value="{DynamicResource SystemControlBackgroundAltHighBrush}"/>
<Setter Property="TopLevel.SystemBarColor" Value="{DynamicResource SystemControlBackgroundAltHighBrush}"/>
<Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}"/> <Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}"/>
<Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}" /> <Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}" />
<Setter Property="Template"> <Setter Property="Template">

1
src/Avalonia.Themes.Fluent/Controls/Window.xaml

@ -3,6 +3,7 @@
<ControlTheme x:Key="{x:Type Window}" TargetType="Window"> <ControlTheme x:Key="{x:Type Window}" TargetType="Window">
<Setter Property="Background" Value="{DynamicResource SystemControlBackgroundAltHighBrush}"/> <Setter Property="Background" Value="{DynamicResource SystemControlBackgroundAltHighBrush}"/>
<Setter Property="TransparencyBackgroundFallback" Value="{DynamicResource SystemControlBackgroundAltHighBrush}" /> <Setter Property="TransparencyBackgroundFallback" Value="{DynamicResource SystemControlBackgroundAltHighBrush}" />
<Setter Property="TopLevel.SystemBarColor" Value="{DynamicResource SystemControlBackgroundAltHighBrush}"/>
<Setter Property="Foreground" Value="{DynamicResource SystemControlForegroundBaseHighBrush}"/> <Setter Property="Foreground" Value="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
<Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}"/> <Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}"/>
<Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}" /> <Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}" />

3
src/Browser/Avalonia.Browser/BrowserInsetsManager.cs

@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Browser.Interop; using Avalonia.Browser.Interop;
using Avalonia.Controls.Platform; using Avalonia.Controls.Platform;
using Avalonia.Media;
using static Avalonia.Controls.Platform.IInsetsManager; using static Avalonia.Controls.Platform.IInsetsManager;
namespace Avalonia.Browser namespace Avalonia.Browser
@ -37,6 +38,8 @@ namespace Avalonia.Browser
} }
} }
public Color? SystemBarColor { get; set; }
public void NotifySafeAreaPaddingChanged() public void NotifySafeAreaPaddingChanged()
{ {
SafeAreaChanged?.Invoke(this, new SafeAreaChangedArgs(SafeAreaPadding)); SafeAreaChanged?.Invoke(this, new SafeAreaChangedArgs(SafeAreaPadding));

3
src/iOS/Avalonia.iOS/InsetsManager.cs

@ -1,5 +1,6 @@
using System; using System;
using Avalonia.Controls.Platform; using Avalonia.Controls.Platform;
using Avalonia.Media;
using UIKit; using UIKit;
namespace Avalonia.iOS; namespace Avalonia.iOS;
@ -80,4 +81,6 @@ internal class InsetsManager : IInsetsManager
} }
public Thickness SafeAreaPadding => _controller?.SafeAreaPadding ?? default; public Thickness SafeAreaPadding => _controller?.SafeAreaPadding ?? default;
public Color? SystemBarColor { get; set; }
} }

Loading…
Cancel
Save