From 44f314acdf678879578c83972b27185f89c125f8 Mon Sep 17 00:00:00 2001 From: Franco Zalamena Date: Fri, 6 Feb 2026 14:09:36 +0000 Subject: [PATCH 1/4] Not making content go behind status bar on fullscreen in-app --- CHANGELOG.md | 4 ++++ .../IterableInAppFragmentHTMLNotification.java | 9 +-------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cb6045b4..c7247c7bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] +### Fixed +- Fixed close button position on full screen in-app messages being obscured by the system status bar. + ## [3.6.5] ### Fixed - Fixed IterableEmbeddedView not having an empty constructor and causing crashes diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java index b6b9a99f6..1a8222457 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java @@ -176,9 +176,7 @@ public void onCancel(DialogInterface dialog) { applyWindowGravity(dialog.getWindow(), "onCreateDialog"); } - if (getInAppLayout(insetPadding) == InAppLayout.FULLSCREEN) { - dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - } else if (getInAppLayout(insetPadding) != InAppLayout.TOP) { + if (getInAppLayout(insetPadding) != InAppLayout.FULLSCREEN && getInAppLayout(insetPadding) != InAppLayout.TOP) { // For TOP layout in-app, status bar will be opaque so that the in-app content does not overlap with translucent status bar. // For other non-fullscreen in-apps layouts (BOTTOM and CENTER), status bar will be translucent dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); @@ -191,10 +189,6 @@ public void onCancel(DialogInterface dialog) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - if (getInAppLayout(insetPadding) == InAppLayout.FULLSCREEN) { - getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - // Set initial window gravity based on inset padding (only for non-fullscreen) if (getInAppLayout(insetPadding) != InAppLayout.FULLSCREEN) { applyWindowGravity(getDialog().getWindow(), "onCreateView"); @@ -623,7 +617,6 @@ public void run() { if (insetPadding.bottom == 0 && insetPadding.top == 0) { //Handle full screen window.setLayout(webViewWidth, webViewHeight); - getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } else { // Resize the WebView directly with explicit size float relativeHeight = height * getResources().getDisplayMetrics().density; From 54225845baa7cfc295890b35923704eddd6f2a2f Mon Sep 17 00:00:00 2001 From: Franco Zalamena Date: Tue, 24 Feb 2026 18:12:47 +0000 Subject: [PATCH 2/4] Matching the app layout style for in-app fullscreen dialogs --- ...IterableInAppFragmentHTMLNotification.java | 87 ++++++++++++------- 1 file changed, 56 insertions(+), 31 deletions(-) diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java index 1a8222457..5a36b9bb0 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java @@ -2,10 +2,8 @@ import android.app.Activity; import android.app.Dialog; -import android.content.Context; import android.content.DialogInterface; import android.graphics.Color; -import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; @@ -16,8 +14,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; -import android.util.DisplayMetrics; -import android.view.Display; import android.view.Gravity; import android.view.LayoutInflater; import android.view.OrientationEventListener; @@ -35,6 +31,7 @@ import androidx.core.graphics.ColorUtils; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; +import androidx.core.view.WindowCompat; import androidx.core.view.WindowInsetsCompat; import androidx.fragment.app.DialogFragment; @@ -78,6 +75,7 @@ public class IterableInAppFragmentHTMLNotification extends DialogFragment implem private boolean shouldAnimate; private double inAppBackgroundAlpha; private String inAppBackgroundColor; + private boolean hostIsEdgeToEdge; public static IterableInAppFragmentHTMLNotification createInstance(@NonNull String htmlString, boolean callbackOnCancel, @NonNull IterableHelper.IterableUrlCallback clickCallback, @NonNull IterableInAppLocation location, @NonNull String messageId, @NonNull Double backgroundAlpha, @NonNull Rect padding) { return IterableInAppFragmentHTMLNotification.createInstance(htmlString, callbackOnCancel, clickCallback, location, messageId, backgroundAlpha, padding, false, new IterableInAppMessage.InAppBgColor(null, 0.0f)); @@ -176,11 +174,8 @@ public void onCancel(DialogInterface dialog) { applyWindowGravity(dialog.getWindow(), "onCreateDialog"); } - if (getInAppLayout(insetPadding) != InAppLayout.FULLSCREEN && getInAppLayout(insetPadding) != InAppLayout.TOP) { - // For TOP layout in-app, status bar will be opaque so that the in-app content does not overlap with translucent status bar. - // For other non-fullscreen in-apps layouts (BOTTOM and CENTER), status bar will be translucent - dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); - } + hostIsEdgeToEdge = isHostActivityEdgeToEdge(); + configureSystemBarBehavior(dialog.getWindow()); return dialog; } @@ -289,9 +284,7 @@ public void run() { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - // Handle edge-to-edge insets with modern approach (only for non-fullscreen) - // Full screen in-apps should not have padding from system bars - if (getInAppLayout(insetPadding) != InAppLayout.FULLSCREEN) { + if (getInAppLayout(insetPadding) != InAppLayout.FULLSCREEN && hostIsEdgeToEdge) { ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> { Insets sysBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(0, sysBars.top, 0, sysBars.bottom); @@ -594,29 +587,11 @@ public void run() { return; } - DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics(); Window window = notification.getDialog().getWindow(); Rect insetPadding = notification.insetPadding; - WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - Point size = new Point(); - - // Get the correct screen size based on api level - // https://stackoverflow.com/questions/35780980/getting-the-actual-screen-height-android - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - display.getRealSize(size); - } else { - display.getSize(size); - } - - int webViewWidth = size.x; - int webViewHeight = size.y; - - //Check if the dialog is full screen if (insetPadding.bottom == 0 && insetPadding.top == 0) { - //Handle full screen - window.setLayout(webViewWidth, webViewHeight); + window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); } else { // Resize the WebView directly with explicit size float relativeHeight = height * getResources().getDisplayMetrics().density; @@ -703,6 +678,56 @@ static int roundToNearest90Degrees(int orientation) { } } + private void configureSystemBarBehavior(Window window) { + if (window == null) return; + Activity activity = getActivity(); + if (activity == null || activity.getWindow() == null) return; + + if (hostIsEdgeToEdge) { + WindowCompat.setDecorFitsSystemWindows(window, false); + window.setStatusBarColor(Color.TRANSPARENT); + window.setNavigationBarColor(Color.TRANSPARENT); + } else { + window.setStatusBarColor(activity.getWindow().getStatusBarColor()); + window.setNavigationBarColor(activity.getWindow().getNavigationBarColor()); + } + } + + private boolean isHostActivityEdgeToEdge() { + Activity activity = getActivity(); + if (activity == null || activity.getWindow() == null) return false; + + if (hasEdgeToEdgeLegacyFlags(activity)) { + return true; + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + return isContentDrawnBehindSystemBars(activity); + } + + return false; + } + + private boolean hasEdgeToEdgeLegacyFlags(Activity activity) { + int flags = activity.getWindow().getDecorView().getSystemUiVisibility(); + return (flags & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0; + } + + private boolean isContentDrawnBehindSystemBars(Activity activity) { + View contentView = activity.findViewById(android.R.id.content); + if (contentView == null) return false; + + int contentTop = getViewTopPositionInWindow(contentView); + boolean statusBarPushesContentDown = contentTop > 0; + return !statusBarPushesContentDown; + } + + private int getViewTopPositionInWindow(View view) { + int[] position = new int[2]; + view.getLocationInWindow(position); + return position[1]; + } + /** * Sets the window gravity based on inset padding * From 7b95ec17b9cbb1ece47a3a21ecb032a816dd5d6a Mon Sep 17 00:00:00 2001 From: Franco Zalamena Date: Tue, 24 Feb 2026 18:19:02 +0000 Subject: [PATCH 3/4] Changelog updated --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7247c7bb..37c869736 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Fixed -- Fixed close button position on full screen in-app messages being obscured by the system status bar. +- In-app messages now match the host app's system bar behavior instead of overriding it. This fixes fullscreen in-apps drawing content behind the status bar. ## [3.6.5] ### Fixed From 78ec60768bb6265d5ec6f2e90b8ae63f6cd61bc5 Mon Sep 17 00:00:00 2001 From: Franco Zalamena Date: Tue, 10 Mar 2026 10:03:50 +0000 Subject: [PATCH 4/4] New config enum to deal with in-app layouts and how they should appear in the app. Changing default bahaviour to follow the app layout --- CHANGELOG.md | 32 +++++- .../iterable/iterableapi/IterableConfig.java | 19 ++++ .../iterableapi/IterableInAppDisplayMode.java | 36 +++++++ ...IterableInAppFragmentHTMLNotification.java | 99 ++++++++++++++++--- 4 files changed, 171 insertions(+), 15 deletions(-) create mode 100644 iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppDisplayMode.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 37c869736..9643918d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,36 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -### Fixed -- In-app messages now match the host app's system bar behavior instead of overriding it. This fixes fullscreen in-apps drawing content behind the status bar. +### Added +- New `IterableInAppDisplayMode` enum to control how in-app messages interact with system bars. Configure via `IterableConfig.Builder.setInAppDisplayMode()`: + - `FOLLOW_APP_LAYOUT` (default) — matches the host app's system bar configuration. No change needed for existing integrations. + - `FORCE_EDGE_TO_EDGE` — forces in-app content to draw behind system bars with transparent status and navigation bars. + - `FORCE_FULLSCREEN` — hides the status bar entirely for all in-app messages. + - `FORCE_RESPECT_BOUNDS` — ensures in-app content never overlaps system bars, keeping UI elements like the close button always accessible. + +### Changed +- In-app messages now match the host app's system bar behavior by default. Previously, fullscreen in-apps would always draw content behind the status bar, which could cause UI elements like the close button to be obscured. The new default (`FOLLOW_APP_LAYOUT`) detects whether your app uses edge-to-edge and matches that configuration. + +### Migration guide +**No action required for most apps.** The new default `FOLLOW_APP_LAYOUT` automatically adapts to your app's layout. + +If you relied on the previous behavior where fullscreen in-apps drew content behind the status bar, you can restore it explicitly: + +```java +// Restore previous behavior: in-app content draws behind system bars +IterableConfig config = new IterableConfig.Builder() + .setInAppDisplayMode(IterableInAppDisplayMode.FORCE_EDGE_TO_EDGE) + .build(); +``` + +If you want to ensure the close button is always accessible regardless of app configuration: + +```java +// In-app content never goes behind system bars +IterableConfig config = new IterableConfig.Builder() + .setInAppDisplayMode(IterableInAppDisplayMode.FORCE_RESPECT_BOUNDS) + .build(); +``` ## [3.6.5] ### Fixed diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java index 6e4bf7c45..2eb0b305f 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java @@ -140,6 +140,12 @@ public class IterableConfig { @Nullable final IterableAPIMobileFrameworkInfo mobileFrameworkInfo; + /** + * Controls how in-app messages interact with the system bars (status bar, navigation bar). + * Defaults to {@link IterableInAppDisplayMode#FOLLOW_APP_LAYOUT}. + */ + final IterableInAppDisplayMode inAppDisplayMode; + /** * Base URL for Webview content loading. Specifically used to enable CORS for external resources. * If null or empty, defaults to empty string (original behavior with about:blank origin). @@ -183,6 +189,7 @@ private IterableConfig(Builder builder) { decryptionFailureHandler = builder.decryptionFailureHandler; mobileFrameworkInfo = builder.mobileFrameworkInfo; webViewBaseUrl = builder.webViewBaseUrl; + inAppDisplayMode = builder.inAppDisplayMode; } public static class Builder { @@ -211,6 +218,7 @@ public static class Builder { private IterableIdentityResolution identityResolution = new IterableIdentityResolution(); private IterableUnknownUserHandler iterableUnknownUserHandler; private String webViewBaseUrl; + private IterableInAppDisplayMode inAppDisplayMode = IterableInAppDisplayMode.FOLLOW_APP_LAYOUT; public Builder() {} @@ -453,6 +461,17 @@ public Builder setMobileFrameworkInfo(@NonNull IterableAPIMobileFrameworkInfo mo return this; } + /** + * Set how in-app messages interact with the system bars (status bar, navigation bar). + * Defaults to {@link IterableInAppDisplayMode#FOLLOW_APP_LAYOUT}, which preserves existing behavior. + * @param inAppDisplayMode the display mode for in-app messages + */ + @NonNull + public Builder setInAppDisplayMode(@NonNull IterableInAppDisplayMode inAppDisplayMode) { + this.inAppDisplayMode = inAppDisplayMode; + return this; + } + /** * Set the base URL for WebView content loading. Used to enable CORS for external resources. * If not set or null, defaults to empty string (original behavior with about:blank origin). diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppDisplayMode.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppDisplayMode.java new file mode 100644 index 000000000..40a326334 --- /dev/null +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppDisplayMode.java @@ -0,0 +1,36 @@ +package com.iterable.iterableapi; + +/** + * Controls how in-app messages interact with the system bars (status bar, navigation bar). + *

+ * This setting is configured via {@link IterableConfig.Builder#setInAppDisplayMode(IterableInAppDisplayMode)} + * and applies globally to all in-app messages displayed by the SDK. + */ +public enum IterableInAppDisplayMode { + + /** + * Default. The in-app message follows the host app's current layout configuration. + * If the app is edge-to-edge, the in-app will display edge-to-edge. + * If the app respects system bar bounds, the in-app will too. + */ + FOLLOW_APP_LAYOUT, + + /** + * Forces in-app messages to display edge-to-edge, drawing content behind system bars. + * The in-app content will extend behind the status bar and navigation bar. + */ + FORCE_EDGE_TO_EDGE, + + /** + * Forces in-app messages to display in fullscreen mode, hiding the status bar entirely. + * Uses legacy FLAG_FULLSCREEN on API < 30 and WindowInsetsController on API 30+. + */ + FORCE_FULLSCREEN, + + /** + * Forces in-app messages to respect system bar boundaries. + * Content will never draw behind the status bar or navigation bar, + * ensuring UI elements like the close button are always accessible. + */ + FORCE_RESPECT_BOUNDS +} diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java index 5a36b9bb0..03904c312 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java @@ -33,6 +33,7 @@ import androidx.core.view.ViewCompat; import androidx.core.view.WindowCompat; import androidx.core.view.WindowInsetsCompat; +import androidx.core.view.WindowInsetsControllerCompat; import androidx.fragment.app.DialogFragment; public class IterableInAppFragmentHTMLNotification extends DialogFragment implements IterableWebView.HTMLNotificationCallbacks { @@ -76,6 +77,7 @@ public class IterableInAppFragmentHTMLNotification extends DialogFragment implem private double inAppBackgroundAlpha; private String inAppBackgroundColor; private boolean hostIsEdgeToEdge; + private IterableInAppDisplayMode displayMode = IterableInAppDisplayMode.FOLLOW_APP_LAYOUT; public static IterableInAppFragmentHTMLNotification createInstance(@NonNull String htmlString, boolean callbackOnCancel, @NonNull IterableHelper.IterableUrlCallback clickCallback, @NonNull IterableInAppLocation location, @NonNull String messageId, @NonNull Double backgroundAlpha, @NonNull Rect padding) { return IterableInAppFragmentHTMLNotification.createInstance(htmlString, callbackOnCancel, clickCallback, location, messageId, backgroundAlpha, padding, false, new IterableInAppMessage.InAppBgColor(null, 0.0f)); @@ -147,6 +149,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) { } notification = this; + displayMode = resolveDisplayMode(); } @NonNull @@ -175,7 +178,7 @@ public void onCancel(DialogInterface dialog) { } hostIsEdgeToEdge = isHostActivityEdgeToEdge(); - configureSystemBarBehavior(dialog.getWindow()); + configureSystemBarsForMode(dialog.getWindow()); return dialog; } @@ -284,7 +287,7 @@ public void run() { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - if (getInAppLayout(insetPadding) != InAppLayout.FULLSCREEN && hostIsEdgeToEdge) { + if (shouldApplySystemBarInsets()) { ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> { Insets sysBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(0, sysBars.top, 0, sysBars.bottom); @@ -494,11 +497,7 @@ public void run() { } }; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - webView.postOnAnimationDelayed(dismissWebViewRunnable, 400); - } else { - webView.postDelayed(dismissWebViewRunnable, 400); - } + webView.postOnAnimationDelayed(dismissWebViewRunnable, 400); } private void processMessageRemoval() { @@ -678,21 +677,94 @@ static int roundToNearest90Degrees(int orientation) { } } - private void configureSystemBarBehavior(Window window) { + private IterableInAppDisplayMode resolveDisplayMode() { + try { + IterableConfig config = IterableApi.sharedInstance.config; + if (config != null) { + return config.inAppDisplayMode; + } + } catch (Exception e) { + IterableLogger.w(TAG, "Could not resolve display mode from config, using default"); + } + return IterableInAppDisplayMode.FOLLOW_APP_LAYOUT; + } + + @SuppressWarnings("deprecation") + private void configureSystemBarsForMode(Window window) { if (window == null) return; + InAppLayout layout = getInAppLayout(insetPadding); + + switch (displayMode) { + case FORCE_EDGE_TO_EDGE: + applyEdgeToEdge(window); + break; + + case FORCE_FULLSCREEN: + hideStatusBar(window); + break; + + case FORCE_RESPECT_BOUNDS: + applyRespectBounds(window); + break; + + case FOLLOW_APP_LAYOUT: + default: + configureSystemBarsFollowingApp(window, layout); + break; + } + } + + private void applyEdgeToEdge(Window window) { + WindowCompat.setDecorFitsSystemWindows(window, false); + // On API 35+, system bars are transparent by default; these setters are no-ops + if (Build.VERSION.SDK_INT < 35) { + window.setStatusBarColor(Color.TRANSPARENT); + window.setNavigationBarColor(Color.TRANSPARENT); + } + } + + @SuppressWarnings("deprecation") + private void hideStatusBar(Window window) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + WindowCompat.setDecorFitsSystemWindows(window, false); + WindowInsetsControllerCompat controller = WindowCompat.getInsetsController(window, window.getDecorView()); + controller.hide(WindowInsetsCompat.Type.statusBars()); + controller.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); + } else { + window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + } + + private void applyRespectBounds(Window window) { + WindowCompat.setDecorFitsSystemWindows(window, true); + } + + @SuppressWarnings("deprecation") + private void configureSystemBarsFollowingApp(Window window, InAppLayout layout) { Activity activity = getActivity(); if (activity == null || activity.getWindow() == null) return; if (hostIsEdgeToEdge) { - WindowCompat.setDecorFitsSystemWindows(window, false); - window.setStatusBarColor(Color.TRANSPARENT); - window.setNavigationBarColor(Color.TRANSPARENT); + applyEdgeToEdge(window); } else { - window.setStatusBarColor(activity.getWindow().getStatusBarColor()); - window.setNavigationBarColor(activity.getWindow().getNavigationBarColor()); + if (Build.VERSION.SDK_INT < 35) { + window.setStatusBarColor(activity.getWindow().getStatusBarColor()); + window.setNavigationBarColor(activity.getWindow().getNavigationBarColor()); + } } } + private boolean shouldApplySystemBarInsets() { + InAppLayout layout = getInAppLayout(insetPadding); + + return switch (displayMode) { + case FORCE_EDGE_TO_EDGE, FORCE_FULLSCREEN -> false; + case FORCE_RESPECT_BOUNDS -> true; + default -> + layout != InAppLayout.FULLSCREEN && hostIsEdgeToEdge; + }; + } + private boolean isHostActivityEdgeToEdge() { Activity activity = getActivity(); if (activity == null || activity.getWindow() == null) return false; @@ -708,6 +780,7 @@ private boolean isHostActivityEdgeToEdge() { return false; } + @SuppressWarnings("deprecation") private boolean hasEdgeToEdgeLegacyFlags(Activity activity) { int flags = activity.getWindow().getDecorView().getSystemUiVisibility(); return (flags & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0;