Skip to content

Commit 0fb31c1

Browse files
author
“Akshay
committed
Cursor Iteration
Needs reduction in code. Lot of repition. Heavy review and testing needed. Committing as inapps are looking stable and are sticking with the layout with back to back phone rotations when inapp performance would fail usually
1 parent dfb9071 commit 0fb31c1

File tree

2 files changed

+229
-17
lines changed

2 files changed

+229
-17
lines changed

iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java

Lines changed: 225 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import android.view.WindowManager;
2727
import android.view.animation.Animation;
2828
import android.view.animation.AnimationUtils;
29+
import android.widget.FrameLayout;
2930
import android.widget.RelativeLayout;
3031

3132
import androidx.annotation.NonNull;
@@ -58,6 +59,12 @@ public class IterableInAppFragmentHTMLNotification extends DialogFragment implem
5859
private boolean callbackOnCancel = false;
5960
private String htmlString;
6061
private String messageId;
62+
63+
// Resize debouncing fields
64+
private Handler resizeHandler = new Handler();
65+
private Runnable pendingResizeRunnable;
66+
private float lastContentHeight = -1;
67+
private static final int RESIZE_DEBOUNCE_DELAY_MS = 200;
6168

6269
private double backgroundAlpha; //TODO: remove in a future version
6370
private Rect insetPadding;
@@ -105,6 +112,35 @@ public IterableInAppFragmentHTMLNotification() {
105112
insetPadding = new Rect();
106113
this.setStyle(DialogFragment.STYLE_NO_FRAME, androidx.appcompat.R.style.Theme_AppCompat_NoActionBar);
107114
}
115+
116+
@Override
117+
public void onStart() {
118+
super.onStart();
119+
120+
// Set dialog positioning after the dialog is created and shown
121+
Dialog dialog = getDialog();
122+
if (dialog != null) {
123+
Window window = dialog.getWindow();
124+
if (window != null) {
125+
WindowManager.LayoutParams windowParams = window.getAttributes();
126+
int startGravity = getVerticalLocation(insetPadding);
127+
128+
if (startGravity == Gravity.CENTER_VERTICAL) {
129+
windowParams.gravity = Gravity.CENTER;
130+
IterableLogger.d(TAG, "Set dialog gravity to CENTER in onStart");
131+
} else if (startGravity == Gravity.TOP) {
132+
windowParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
133+
IterableLogger.d(TAG, "Set dialog gravity to TOP in onStart");
134+
} else if (startGravity == Gravity.BOTTOM) {
135+
windowParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
136+
IterableLogger.d(TAG, "Set dialog gravity to BOTTOM in onStart");
137+
}
138+
139+
window.setAttributes(windowParams);
140+
IterableLogger.d(TAG, "Applied window gravity in onStart: " + windowParams.gravity);
141+
}
142+
}
143+
}
108144

109145
@Override
110146
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -144,6 +180,25 @@ public void onCancel(DialogInterface dialog) {
144180
}
145181
});
146182
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
183+
184+
// Set window gravity for the dialog
185+
Window window = dialog.getWindow();
186+
WindowManager.LayoutParams windowParams = window.getAttributes();
187+
int dialogGravity = getVerticalLocation(insetPadding);
188+
189+
if (dialogGravity == Gravity.CENTER_VERTICAL) {
190+
windowParams.gravity = Gravity.CENTER;
191+
IterableLogger.d(TAG, "Set dialog gravity to CENTER in onCreateDialog");
192+
} else if (dialogGravity == Gravity.TOP) {
193+
windowParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
194+
IterableLogger.d(TAG, "Set dialog gravity to TOP in onCreateDialog");
195+
} else if (dialogGravity == Gravity.BOTTOM) {
196+
windowParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
197+
IterableLogger.d(TAG, "Set dialog gravity to BOTTOM in onCreateDialog");
198+
}
199+
200+
window.setAttributes(windowParams);
201+
147202
if (getInAppLayout(insetPadding) == InAppLayout.FULLSCREEN) {
148203
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
149204
} else if (getInAppLayout(insetPadding) != InAppLayout.TOP) {
@@ -162,41 +217,111 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
162217
if (getInAppLayout(insetPadding) == InAppLayout.FULLSCREEN) {
163218
getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
164219
}
220+
221+
// Set initial window gravity based on inset padding
222+
Window window = getDialog().getWindow();
223+
WindowManager.LayoutParams windowParams = window.getAttributes();
224+
int windowGravity = getVerticalLocation(insetPadding);
225+
226+
if (windowGravity == Gravity.CENTER_VERTICAL) {
227+
windowParams.gravity = Gravity.CENTER;
228+
IterableLogger.d(TAG, "Set initial CENTER window gravity in onCreateView");
229+
} else if (windowGravity == Gravity.TOP) {
230+
windowParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
231+
IterableLogger.d(TAG, "Set initial TOP window gravity in onCreateView");
232+
} else if (windowGravity == Gravity.BOTTOM) {
233+
windowParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
234+
IterableLogger.d(TAG, "Set initial BOTTOM window gravity in onCreateView");
235+
}
236+
237+
window.setAttributes(windowParams);
165238

166239
webView = new IterableWebView(getContext());
167240
webView.setId(R.id.webView);
241+
242+
// Debug the HTML content
243+
IterableLogger.d(TAG, "HTML content preview: " + (htmlString.length() > 200 ? htmlString.substring(0, 200) + "..." : htmlString));
244+
168245
webView.createWithHtml(this, htmlString);
169246

170247
if (orientationListener == null) {
171248
orientationListener = new OrientationEventListener(getContext(), SensorManager.SENSOR_DELAY_NORMAL) {
249+
private int lastOrientation = -1;
250+
172251
// Resize the webView on device rotation
173252
public void onOrientationChanged(int orientation) {
174-
if (loaded) {
175-
final Handler handler = new Handler();
176-
handler.postDelayed(new Runnable() {
177-
@Override
178-
public void run() {
179-
runResizeScript();
180-
}
181-
}, 1000);
253+
if (loaded && webView != null) {
254+
// Only trigger on significant orientation changes (90 degree increments)
255+
int currentOrientation = ((orientation + 45) / 90) * 90;
256+
if (currentOrientation != lastOrientation && lastOrientation != -1) {
257+
lastOrientation = currentOrientation;
258+
259+
// Use longer delay for orientation changes to allow layout to stabilize
260+
final Handler handler = new Handler();
261+
handler.postDelayed(new Runnable() {
262+
@Override
263+
public void run() {
264+
IterableLogger.d(TAG, "Orientation changed, triggering resize");
265+
runResizeScript();
266+
}
267+
}, 1500); // Increased delay for better stability
268+
} else if (lastOrientation == -1) {
269+
lastOrientation = currentOrientation;
270+
}
182271
}
183272
}
184273
};
185274
}
186275

187276
orientationListener.enable();
188277

189-
RelativeLayout relativeLayout = new RelativeLayout(this.getContext());
190-
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
191-
relativeLayout.setVerticalGravity(getVerticalLocation(insetPadding));
192-
relativeLayout.addView(webView, layoutParams);
278+
// Create a FrameLayout as the main container for better positioning control
279+
FrameLayout frameLayout = new FrameLayout(this.getContext());
280+
281+
// Create a RelativeLayout as a wrapper for the WebView
282+
RelativeLayout webViewContainer = new RelativeLayout(this.getContext());
283+
284+
int gravity = getVerticalLocation(insetPadding);
285+
IterableLogger.d(TAG, "Initial setup - gravity: " + gravity + " for inset padding: " + insetPadding);
286+
287+
// Set FrameLayout gravity based on positioning
288+
FrameLayout.LayoutParams containerParams = new FrameLayout.LayoutParams(
289+
FrameLayout.LayoutParams.MATCH_PARENT,
290+
FrameLayout.LayoutParams.WRAP_CONTENT
291+
);
292+
293+
if (gravity == Gravity.CENTER_VERTICAL) {
294+
containerParams.gravity = Gravity.CENTER;
295+
IterableLogger.d(TAG, "Applied CENTER gravity to container");
296+
} else if (gravity == Gravity.TOP) {
297+
containerParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
298+
IterableLogger.d(TAG, "Applied TOP gravity to container");
299+
} else if (gravity == Gravity.BOTTOM) {
300+
containerParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
301+
IterableLogger.d(TAG, "Applied BOTTOM gravity to container");
302+
}
303+
304+
// Add WebView to the RelativeLayout container with WRAP_CONTENT for proper sizing
305+
RelativeLayout.LayoutParams webViewParams = new RelativeLayout.LayoutParams(
306+
RelativeLayout.LayoutParams.WRAP_CONTENT,
307+
RelativeLayout.LayoutParams.WRAP_CONTENT
308+
);
309+
webViewParams.addRule(RelativeLayout.CENTER_IN_PARENT);
310+
webViewContainer.addView(webView, webViewParams);
311+
312+
IterableLogger.d(TAG, "Added WebView with WRAP_CONTENT and CENTER_IN_PARENT rule");
313+
314+
// Add the container to the FrameLayout
315+
frameLayout.addView(webViewContainer, containerParams);
316+
317+
IterableLogger.d(TAG, "Created FrameLayout with positioned RelativeLayout container");
193318

194319
if (savedInstanceState == null || !savedInstanceState.getBoolean(IN_APP_OPEN_TRACKED, false)) {
195320
IterableApi.sharedInstance.trackInAppOpen(messageId, location);
196321
}
197322

198323
prepareToShowWebView();
199-
return relativeLayout;
324+
return frameLayout;
200325
}
201326

202327
public void setLoaded(boolean loaded) {
@@ -226,6 +351,12 @@ public void onStop() {
226351
public void onDestroy() {
227352
super.onDestroy();
228353

354+
// Clean up pending resize operations
355+
if (resizeHandler != null && pendingResizeRunnable != null) {
356+
resizeHandler.removeCallbacks(pendingResizeRunnable);
357+
pendingResizeRunnable = null;
358+
}
359+
229360
if (this.getActivity() != null && this.getActivity().isChangingConfigurations()) {
230361
return;
231362
}
@@ -414,7 +545,50 @@ private void processMessageRemoval() {
414545

415546
@Override
416547
public void runResizeScript() {
417-
resize(webView.getContentHeight());
548+
// Cancel any pending resize operation
549+
if (pendingResizeRunnable != null) {
550+
resizeHandler.removeCallbacks(pendingResizeRunnable);
551+
}
552+
553+
// Schedule a debounced resize operation
554+
pendingResizeRunnable = new Runnable() {
555+
@Override
556+
public void run() {
557+
performResizeWithValidation();
558+
}
559+
};
560+
561+
resizeHandler.postDelayed(pendingResizeRunnable, RESIZE_DEBOUNCE_DELAY_MS);
562+
}
563+
564+
private void performResizeWithValidation() {
565+
if (webView == null) {
566+
IterableLogger.w(TAG, "WebView is null, skipping resize");
567+
return;
568+
}
569+
570+
float currentHeight = webView.getContentHeight();
571+
572+
// Validate content height
573+
if (currentHeight <= 0) {
574+
IterableLogger.w(TAG, "Invalid content height: " + currentHeight + "dp, skipping resize");
575+
return;
576+
}
577+
578+
// Check if height has stabilized (avoid unnecessary resizes for same height)
579+
if (Math.abs(currentHeight - lastContentHeight) < 1.0f) {
580+
IterableLogger.d(TAG, "Content height unchanged (" + currentHeight + "dp), skipping resize");
581+
return;
582+
}
583+
584+
lastContentHeight = currentHeight;
585+
586+
IterableLogger.d(
587+
TAG,
588+
"💚 Resizing in-app to height: " + currentHeight + "dp"
589+
);
590+
591+
resize(currentHeight);
418592
}
419593

420594
/**
@@ -462,9 +636,44 @@ public void run() {
462636
window.setLayout(webViewWidth, webViewHeight);
463637
getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
464638
} else {
639+
// Resize the WebView directly with explicit size
465640
float relativeHeight = height * getResources().getDisplayMetrics().density;
466-
RelativeLayout.LayoutParams webViewLayout = new RelativeLayout.LayoutParams(getResources().getDisplayMetrics().widthPixels, (int) relativeHeight);
467-
webView.setLayoutParams(webViewLayout);
641+
int newWebViewWidth = getResources().getDisplayMetrics().widthPixels;
642+
int newWebViewHeight = (int) relativeHeight;
643+
644+
// Set WebView to explicit size
645+
RelativeLayout.LayoutParams webViewParams = new RelativeLayout.LayoutParams(newWebViewWidth, newWebViewHeight);
646+
647+
// Apply positioning based on gravity
648+
int resizeGravity = getVerticalLocation(insetPadding);
649+
IterableLogger.d(TAG, "Resizing WebView directly - gravity: " + resizeGravity + " size: " + newWebViewWidth + "x" + newWebViewHeight + "px for inset padding: " + insetPadding);
650+
651+
if (resizeGravity == Gravity.CENTER_VERTICAL) {
652+
webViewParams.addRule(RelativeLayout.CENTER_IN_PARENT);
653+
IterableLogger.d(TAG, "Applied CENTER_IN_PARENT to WebView");
654+
} else if (resizeGravity == Gravity.TOP) {
655+
webViewParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
656+
webViewParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
657+
IterableLogger.d(TAG, "Applied TOP alignment to WebView");
658+
} else if (resizeGravity == Gravity.BOTTOM) {
659+
webViewParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
660+
webViewParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
661+
IterableLogger.d(TAG, "Applied BOTTOM alignment to WebView");
662+
}
663+
664+
// Make dialog full screen to allow proper positioning
665+
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
666+
667+
// Apply the new layout params to WebView
668+
webView.setLayoutParams(webViewParams);
669+
670+
// Force layout updates
671+
webView.requestLayout();
672+
if (webView.getParent() instanceof ViewGroup) {
673+
((ViewGroup) webView.getParent()).requestLayout();
674+
}
675+
676+
IterableLogger.d(TAG, "Applied explicit size and positioning to WebView: " + newWebViewWidth + "x" + newWebViewHeight);
468677
}
469678
} catch (IllegalArgumentException e) {
470679
IterableLogger.e(TAG, "Exception while trying to resize an in-app message", e);

iterableapi/src/main/java/com/iterable/iterableapi/IterableWebChromeClient.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ public class IterableWebChromeClient extends WebChromeClient {
1212

1313
@Override
1414
public void onProgressChanged(WebView view, int newProgress) {
15-
inAppHTMLNotification.runResizeScript();
15+
// Only trigger resize when page is fully loaded (100%) to avoid multiple rapid calls
16+
if (newProgress == 100) {
17+
inAppHTMLNotification.runResizeScript();
18+
}
1619
}
1720
}

0 commit comments

Comments
 (0)