Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 85 additions & 32 deletions src/CommunityToolkit.Maui.Core/Platform/StatusBar/StatusBar.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ namespace CommunityToolkit.Maui.Core.Platform;
[SupportedOSPlatform("Android23.0")] // StatusBar is only supported on Android 23.0+
static partial class StatusBar
{
const string statusBarOverlayTag = "StatusBarOverlay";

static readonly Lazy<bool> isSupportedHolder = new(() =>
{
if (OperatingSystem.IsAndroidVersionAtLeast((int)BuildVersionCodes.M))
Expand All @@ -30,63 +32,114 @@ static partial class StatusBar

static void PlatformSetColor(Color color)
{
if (!IsSupported)
if (!IsSupported || Activity.GetCurrentWindow() is not Window { DecorView.RootView: not null } window)
{
return;
}

if (Activity.GetCurrentWindow() is not Window { DecorView.RootView: not null } window)
var platformColor = color.ToPlatform();
var decorGroup = (ViewGroup)window.DecorView.RootView;
if (!OperatingSystem.IsAndroidVersionAtLeast(35))
{
return;
PlatformSetColor_AndroidApiLessThan35(window, platformColor);
}

var platformColor = color.ToPlatform();

if (OperatingSystem.IsAndroidVersionAtLeast(35))
else if (OperatingSystem.IsAndroidVersionAtLeast(36))
{
PlatformSetColor_AndroidApi36AndHigher(window, platformColor, decorGroup);
}
else
{
const string statusBarOverlayTag = "StatusBarOverlay";
PlatformSetColor_AndroidApi35(window, platformColor, decorGroup);
}
}

var decorGroup = (ViewGroup)window.DecorView.RootView;
var statusBarOverlay = decorGroup.FindViewWithTag(statusBarOverlayTag);
[SupportedOSPlatform("android36.0")]
static void PlatformSetColor_AndroidApi36AndHigher(Window window, PlatformColor platformColor, ViewGroup decorGroup)
{
var statusBarOverlay = decorGroup.FindViewWithTag(statusBarOverlayTag);

if (statusBarOverlay is null)
if (statusBarOverlay is null)
{
window.DecorView.Post(() =>
{
var statusBarHeight = Activity.Resources?.GetIdentifier("status_bar_height", "dimen", "android") ?? 0;
var statusBarPixelSize = statusBarHeight > 0 ? Activity.Resources?.GetDimensionPixelSize(statusBarHeight) ?? 0 : 0;

statusBarOverlay = new(Activity)
{
LayoutParameters = new FrameLayout.LayoutParams(Android.Views.ViewGroup.LayoutParams.MatchParent, statusBarPixelSize + 3)
{
Gravity = GravityFlags.Top
}
};

statusBarOverlay.Tag = statusBarOverlayTag;
decorGroup.AddView(statusBarOverlay);
statusBarOverlay.SetZ(0);
}
var insets = window.DecorView.RootWindowInsets;
var height = insets?.GetInsets(WindowInsets.Type.StatusBars()).Top ?? 0;

ApplyStatusBarOverlay(height, platformColor, decorGroup);
Comment thread
TheCodeTraveler marked this conversation as resolved.
ApplyWindowFlags(window, platformColor);
});
}
else
{
statusBarOverlay.SetBackgroundColor(platformColor);
ApplyWindowFlags(window, platformColor);
}
}

[SupportedOSPlatform("android35.0"), UnsupportedOSPlatform("android36.0")]
static void PlatformSetColor_AndroidApi35(in Window window, in PlatformColor platformColor, in ViewGroup decorGroup)
{
var statusBarOverlay = decorGroup.FindViewWithTag(statusBarOverlayTag);
if (statusBarOverlay is null)
{
var resId = Activity.Resources?.GetIdentifier("status_bar_height", "dimen", "android") ?? 0;
var height = resId > 0
? Activity.Resources?.GetDimensionPixelSize(resId) ?? 0
: 0;

ApplyStatusBarOverlay(height, platformColor, decorGroup);
}
else
{
window.SetStatusBarColor(platformColor);
statusBarOverlay.SetBackgroundColor(platformColor);
}

bool isColorTransparent = platformColor == PlatformColor.Transparent;
if (isColorTransparent)
ApplyWindowFlags(window, platformColor);
}

[SupportedOSPlatform("android"), UnsupportedOSPlatform("android35.0")]
static void PlatformSetColor_AndroidApiLessThan35(in Window window, in PlatformColor platformColor)
Comment thread
TheCodeTraveler marked this conversation as resolved.
{
window.SetStatusBarColor(platformColor);
ApplyWindowFlags(window, platformColor);
}

static void ApplyStatusBarOverlay(int height, PlatformColor platformColor, ViewGroup decorGroup)
{
var statusBarOverlay = new View(Activity)
{
LayoutParameters = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MatchParent,
height + 3)
Comment thread
TheCodeTraveler marked this conversation as resolved.
{
Gravity = GravityFlags.Top
},
Tag = statusBarOverlayTag
};

decorGroup.AddView(statusBarOverlay);
statusBarOverlay.SetZ(0);
statusBarOverlay.SetBackgroundColor(platformColor);
}

static void ApplyWindowFlags(Window window, PlatformColor platformColor)
{
bool isTransparent = platformColor == PlatformColor.Transparent;

if (isTransparent)
{
window.ClearFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
window.SetFlags(WindowManagerFlags.LayoutNoLimits, WindowManagerFlags.LayoutNoLimits);
}
else
{
window.ClearFlags(WindowManagerFlags.LayoutNoLimits);
window.SetFlags(WindowManagerFlags.DrawsSystemBarBackgrounds, WindowManagerFlags.DrawsSystemBarBackgrounds);
window.SetFlags(
WindowManagerFlags.DrawsSystemBarBackgrounds,
WindowManagerFlags.DrawsSystemBarBackgrounds);
}

WindowCompat.SetDecorFitsSystemWindows(window, !isColorTransparent);
WindowCompat.SetDecorFitsSystemWindows(window, !isTransparent);
}

static void PlatformSetStyle(StatusBarStyle style)
Expand Down Expand Up @@ -115,7 +168,7 @@ static void PlatformSetStyle(StatusBarStyle style)
static void SetStatusBarAppearance(bool isLightStatusBars)
{
if (Activity.GetCurrentWindow() is Window window
&& WindowCompat.GetInsetsController(window, window.DecorView) is WindowInsetsControllerCompat windowController)
&& WindowCompat.GetInsetsController(window, window.DecorView) is WindowInsetsControllerCompat windowController)
{
windowController.AppearanceLightStatusBars = isLightStatusBars;
}
Expand Down
Loading