From 44f314acdf678879578c83972b27185f89c125f8 Mon Sep 17 00:00:00 2001 From: Franco Zalamena Date: Fri, 6 Feb 2026 14:09:36 +0000 Subject: [PATCH 1/3] 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/3] 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/3] 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