capacitor-plugin-status-bar 2.0.10 → 2.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -21,7 +21,6 @@ import androidx.core.view.WindowInsetsCompat;
|
|
|
21
21
|
|
|
22
22
|
import com.getcapacitor.Plugin;
|
|
23
23
|
|
|
24
|
-
|
|
25
24
|
/**
|
|
26
25
|
* Android Status Bar utilities with Android 10-15+ (API 29-35+) support.
|
|
27
26
|
* Supports:
|
|
@@ -42,39 +41,39 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
42
41
|
private int currentStatusBarColor = Color.BLACK;
|
|
43
42
|
private int currentNavBarColor = Color.BLACK;
|
|
44
43
|
|
|
45
|
-
// Note: load() is not called since CapacitorStatusBar is instantiated via new
|
|
44
|
+
// Note: load() is not called since CapacitorStatusBar is instantiated via new
|
|
45
|
+
// CapacitorStatusBar()
|
|
46
46
|
// from CapacitorStatusBarPlugin, not registered as a Capacitor plugin itself.
|
|
47
|
-
// All initialization happens via ensureEdgeToEdgeConfigured() called from
|
|
47
|
+
// All initialization happens via ensureEdgeToEdgeConfigured() called from
|
|
48
|
+
// CapacitorStatusBarPlugin.load().
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
|
-
* Ensures edge-to-edge is properly configured for Android
|
|
51
|
-
* Sets up a unified insets listener on the decorView that handles
|
|
52
|
-
*
|
|
51
|
+
* Ensures edge-to-edge is properly configured for Android 12+.
|
|
52
|
+
* Sets up a unified insets listener on the decorView that handles
|
|
53
|
+
* overlay view sizing and WebView padding so content stays within
|
|
54
|
+
* the safe area.
|
|
53
55
|
*
|
|
54
56
|
* @param activity The activity to configure
|
|
57
|
+
* @param webView The Capacitor WebView to apply safe-area padding to (may be null)
|
|
55
58
|
*/
|
|
56
|
-
public void ensureEdgeToEdgeConfigured(Activity activity) {
|
|
59
|
+
public void ensureEdgeToEdgeConfigured(Activity activity, @Nullable View webView) {
|
|
57
60
|
Window window = activity.getWindow();
|
|
58
61
|
View decorView = window.getDecorView();
|
|
59
62
|
|
|
60
63
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
61
|
-
// Android 12+ (API 31+): enable edge-to-edge layout.
|
|
62
|
-
// The nav bar uses overlay views because gesture navigation ignores setNavigationBarColor().
|
|
63
|
-
// The status bar still uses setStatusBarColor() reliably on API 31–34;
|
|
64
|
-
// overlay is only needed on API 35+ where edge-to-edge is enforced and the native API is a no-op.
|
|
65
64
|
WindowCompat.setDecorFitsSystemWindows(window, false);
|
|
66
65
|
|
|
67
|
-
// Set a transparent baseline; setStyle() will apply the actual color via setStatusBarColor()
|
|
68
|
-
// (API 31-34) or the status bar overlay (API 35+).
|
|
69
66
|
window.setStatusBarColor(Color.TRANSPARENT);
|
|
70
67
|
window.setNavigationBarColor(Color.TRANSPARENT);
|
|
71
68
|
window.setStatusBarContrastEnforced(false);
|
|
72
69
|
window.setNavigationBarContrastEnforced(false);
|
|
73
70
|
|
|
74
|
-
// Single unified insets listener on decorView for overlay sizing
|
|
75
71
|
ViewCompat.setOnApplyWindowInsetsListener(decorView, (v, insets) -> {
|
|
76
|
-
// Size status bar overlay
|
|
77
72
|
int top = insets.getInsets(WindowInsetsCompat.Type.statusBars()).top;
|
|
73
|
+
int navBottom = insets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom;
|
|
74
|
+
boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
|
|
75
|
+
|
|
76
|
+
// Size status bar overlay
|
|
78
77
|
View statusOverlay = ((ViewGroup) v).findViewWithTag(STATUS_BAR_OVERLAY_TAG);
|
|
79
78
|
if (statusOverlay != null) {
|
|
80
79
|
ViewGroup.LayoutParams params = statusOverlay.getLayoutParams();
|
|
@@ -85,27 +84,49 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
85
84
|
}
|
|
86
85
|
}
|
|
87
86
|
|
|
88
|
-
// Size navigation bar overlay
|
|
89
|
-
|
|
87
|
+
// Size navigation bar overlay — collapse it when the keyboard is
|
|
88
|
+
// open since the nav bar is hidden behind the IME.
|
|
89
|
+
int overlayBottom = imeVisible ? 0 : navBottom;
|
|
90
90
|
View navOverlay = ((ViewGroup) v).findViewWithTag(NAV_BAR_OVERLAY_TAG);
|
|
91
91
|
if (navOverlay != null) {
|
|
92
92
|
ViewGroup.LayoutParams params = navOverlay.getLayoutParams();
|
|
93
|
-
if (params.height !=
|
|
94
|
-
params.height =
|
|
93
|
+
if (params.height != overlayBottom) {
|
|
94
|
+
params.height = overlayBottom;
|
|
95
95
|
navOverlay.setLayoutParams(params);
|
|
96
|
-
Log.d(TAG, "insetsListener: nav bar overlay height=" +
|
|
96
|
+
Log.d(TAG, "insetsListener: nav bar overlay height=" + overlayBottom
|
|
97
|
+
+ " (imeVisible=" + imeVisible + ")");
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
// Inset the WebView via layout margins so it never renders behind
|
|
102
|
+
// system bars. When the keyboard is open the nav bar is behind the
|
|
103
|
+
// IME, so drop the bottom margin to avoid a gap above the keyboard.
|
|
104
|
+
if (webView != null
|
|
105
|
+
&& webView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
|
|
106
|
+
ViewGroup.MarginLayoutParams mlp =
|
|
107
|
+
(ViewGroup.MarginLayoutParams) webView.getLayoutParams();
|
|
108
|
+
int left = insets.getInsets(WindowInsetsCompat.Type.systemBars()).left;
|
|
109
|
+
int right = insets.getInsets(WindowInsetsCompat.Type.systemBars()).right;
|
|
110
|
+
int bottomMargin = imeVisible ? 0 : navBottom;
|
|
111
|
+
if (mlp.topMargin != top || mlp.bottomMargin != bottomMargin
|
|
112
|
+
|| mlp.leftMargin != left || mlp.rightMargin != right) {
|
|
113
|
+
mlp.topMargin = top;
|
|
114
|
+
mlp.bottomMargin = bottomMargin;
|
|
115
|
+
mlp.leftMargin = left;
|
|
116
|
+
mlp.rightMargin = right;
|
|
117
|
+
webView.setLayoutParams(mlp);
|
|
118
|
+
Log.d(TAG, "insetsListener: webView margins t=" + top
|
|
119
|
+
+ " b=" + bottomMargin + " l=" + left + " r=" + right
|
|
120
|
+
+ " (imeVisible=" + imeVisible + ")");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return WindowInsetsCompat.CONSUMED;
|
|
102
125
|
});
|
|
103
126
|
|
|
127
|
+
decorView.requestApplyInsets();
|
|
104
128
|
Log.d(TAG, "ensureEdgeToEdgeConfigured: edge-to-edge with overlay views, API=" + Build.VERSION.SDK_INT);
|
|
105
129
|
} else {
|
|
106
|
-
// Android < 12 (API < 31): Only disable contrast enforcement.
|
|
107
|
-
// Do NOT call setDecorFitsSystemWindows(false), create overlay views, or set insets listener.
|
|
108
|
-
// This avoids conflicts with plugins like @capawesome/capacitor-android-edge-to-edge-support.
|
|
109
130
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
110
131
|
window.setStatusBarContrastEnforced(false);
|
|
111
132
|
window.setNavigationBarContrastEnforced(false);
|
|
@@ -157,57 +178,42 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
157
178
|
showNavigationBar(activity, true);
|
|
158
179
|
}
|
|
159
180
|
|
|
160
|
-
public void hideStatusBar(Activity activity
|
|
161
|
-
Log.d(TAG, "hideStatusBar: animation=" + animation + ", API=" + Build.VERSION.SDK_INT);
|
|
181
|
+
public void hideStatusBar(Activity activity) {
|
|
162
182
|
Window window = activity.getWindow();
|
|
163
183
|
View decorView = window.getDecorView();
|
|
164
184
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if ("fade".equals(animationType)) {
|
|
168
|
-
// Fade mode: Make background transparent without removing status bar and
|
|
169
|
-
// navigation bar
|
|
170
|
-
Log.d(TAG, "hideStatusBar: fade mode - making backgrounds transparent");
|
|
171
|
-
makeStatusBarBackgroundTransparent(activity);
|
|
172
|
-
hideNavigationBar(activity, "fade");
|
|
173
|
-
} else if ("slide".equals(animationType)) {
|
|
174
|
-
// Slide mode: Hide status bar and navigation bar completely (current behavior)
|
|
175
|
-
Log.d(TAG, "hideStatusBar: slide mode - hiding bars completely");
|
|
185
|
+
// Slide mode: Hide status bar and navigation bar completely (current behavior)
|
|
186
|
+
Log.d(TAG, "hideStatusBar: slide mode - hiding bars completely");
|
|
176
187
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
} else {
|
|
188
|
-
Log.w(TAG, "hideStatusBar: WindowInsetsController is null");
|
|
189
|
-
}
|
|
188
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
189
|
+
// API 30+ (Android 11+) - Use WindowInsetsController
|
|
190
|
+
WindowInsetsController controller = window.getInsetsController();
|
|
191
|
+
if (controller != null) {
|
|
192
|
+
Log.d(TAG, "hideStatusBar: hiding system bars (API 30+)");
|
|
193
|
+
// Hide both status and navigation bars together
|
|
194
|
+
controller.hide(WindowInsets.Type.systemBars());
|
|
195
|
+
// Set behavior for immersive mode (user can swipe to reveal temporarily)
|
|
196
|
+
controller.setSystemBarsBehavior(
|
|
197
|
+
WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
|
190
198
|
} else {
|
|
191
|
-
|
|
192
|
-
// necessary)
|
|
193
|
-
Log.d(TAG, "hideStatusBar: hiding using system UI flags (API 29)");
|
|
194
|
-
// Use immersive sticky mode with proper layout flags for Android 10
|
|
195
|
-
decorView.setSystemUiVisibility(
|
|
196
|
-
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
|
197
|
-
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
|
198
|
-
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
|
199
|
-
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
|
200
|
-
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
|
201
|
-
| View.SYSTEM_UI_FLAG_FULLSCREEN);
|
|
199
|
+
Log.w(TAG, "hideStatusBar: WindowInsetsController is null");
|
|
202
200
|
}
|
|
203
|
-
|
|
204
|
-
// Make the overlay backgrounds transparent so content shows through
|
|
205
|
-
makeStatusBarBackgroundTransparent(activity);
|
|
206
201
|
} else {
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
|
|
202
|
+
// API 29 (Android 10) - Use system UI visibility flags (deprecated but
|
|
203
|
+
// necessary)
|
|
204
|
+
Log.d(TAG, "hideStatusBar: hiding using system UI flags (API 29)");
|
|
205
|
+
// Use immersive sticky mode with proper layout flags for Android 10
|
|
206
|
+
decorView.setSystemUiVisibility(
|
|
207
|
+
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
|
208
|
+
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
|
209
|
+
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
|
210
|
+
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
|
211
|
+
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
|
212
|
+
| View.SYSTEM_UI_FLAG_FULLSCREEN);
|
|
210
213
|
}
|
|
214
|
+
|
|
215
|
+
// Make the overlay backgrounds transparent so content shows through
|
|
216
|
+
makeStatusBarBackgroundTransparent(activity);
|
|
211
217
|
}
|
|
212
218
|
|
|
213
219
|
public void setStyle(Activity activity, String style, @Nullable String colorHex) {
|
|
@@ -262,7 +268,8 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
262
268
|
}
|
|
263
269
|
|
|
264
270
|
// Set icon appearance AFTER background operations.
|
|
265
|
-
// On Android 13 (API 33), applyStatusBarBackground triggers
|
|
271
|
+
// On Android 13 (API 33), applyStatusBarBackground triggers
|
|
272
|
+
// requestApplyInsets()
|
|
266
273
|
// which causes the WindowInsetsController to reset setSystemBarsAppearance.
|
|
267
274
|
// Calling setLightStatusBarIcons last ensures the icon style is not overridden.
|
|
268
275
|
setLightStatusBarIcons(window, lightBackground);
|
|
@@ -291,7 +298,8 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
291
298
|
* Returns the insets for status bar, navigation bar, and notch areas.
|
|
292
299
|
*
|
|
293
300
|
* @param activity The activity to get the insets from
|
|
294
|
-
* @return A map containing top, bottom, left, and right inset values in dp
|
|
301
|
+
* @return A map containing top, bottom, left, and right inset values in dp
|
|
302
|
+
* (density-independent pixels)
|
|
295
303
|
*/
|
|
296
304
|
public java.util.Map<String, Integer> getSafeAreaInsets(Activity activity) {
|
|
297
305
|
Log.d(TAG, "getSafeAreaInsets");
|
|
@@ -302,10 +310,12 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
302
310
|
WindowInsetsCompat windowInsets = ViewCompat.getRootWindowInsets(decorView);
|
|
303
311
|
|
|
304
312
|
if (windowInsets != null) {
|
|
305
|
-
// Use WindowInsetsCompat for accurate, type-specific insets across all API
|
|
313
|
+
// Use WindowInsetsCompat for accurate, type-specific insets across all API
|
|
314
|
+
// levels
|
|
306
315
|
androidx.core.graphics.Insets statusBars = windowInsets.getInsets(WindowInsetsCompat.Type.statusBars());
|
|
307
316
|
androidx.core.graphics.Insets navBars = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars());
|
|
308
|
-
androidx.core.graphics.Insets displayCutout = windowInsets
|
|
317
|
+
androidx.core.graphics.Insets displayCutout = windowInsets
|
|
318
|
+
.getInsets(WindowInsetsCompat.Type.displayCutout());
|
|
309
319
|
|
|
310
320
|
int topPx = Math.max(statusBars.top, displayCutout.top);
|
|
311
321
|
int bottomPx = Math.max(navBars.bottom, displayCutout.bottom);
|
|
@@ -499,12 +509,12 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
499
509
|
|
|
500
510
|
private void applyStatusBarBackground(Activity activity, @ColorInt int color) {
|
|
501
511
|
Log.d(TAG, "applyStatusBarBackground: color=#" + Integer.toHexString(color) + ", API=" + Build.VERSION.SDK_INT);
|
|
502
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.
|
|
503
|
-
//
|
|
512
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
513
|
+
// API 31+: edge-to-edge is enabled, setStatusBarColor() is unreliable.
|
|
514
|
+
// Use an overlay View drawn on top of the status bar area.
|
|
504
515
|
ensureStatusBarOverlay(activity, color);
|
|
505
516
|
} else {
|
|
506
|
-
// API 29–
|
|
507
|
-
// Note: gesture navigation only ignores setNavigationBarColor(), not setStatusBarColor().
|
|
517
|
+
// API 29–30: no edge-to-edge, native API works reliably.
|
|
508
518
|
activity.getWindow().setStatusBarColor(color);
|
|
509
519
|
}
|
|
510
520
|
}
|
|
@@ -512,13 +522,13 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
512
522
|
private void applyNavigationBarBackground(Activity activity, @ColorInt int color) {
|
|
513
523
|
Log.d(TAG, "applyNavigationBarBackground: color=#" + Integer.toHexString(color) + ", API="
|
|
514
524
|
+ Build.VERSION.SDK_INT);
|
|
515
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.
|
|
516
|
-
//
|
|
525
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
526
|
+
// API 31+: edge-to-edge is enabled, setNavigationBarColor() is unreliable
|
|
527
|
+
// (especially gesture navigation which ignores it entirely).
|
|
528
|
+
// Use an overlay View drawn at the bottom of the screen.
|
|
517
529
|
ensureNavBarOverlay(activity, color);
|
|
518
530
|
} else {
|
|
519
|
-
// API 29–
|
|
520
|
-
// Gesture navigation ignores it (system enforces transparency for gesture handles),
|
|
521
|
-
// but in that case there is no visible nav bar to color anyway.
|
|
531
|
+
// API 29–30: no edge-to-edge, native API works for button navigation.
|
|
522
532
|
activity.getWindow().setNavigationBarColor(color);
|
|
523
533
|
}
|
|
524
534
|
}
|
|
@@ -547,7 +557,8 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
547
557
|
overlay.setLayoutParams(lp);
|
|
548
558
|
|
|
549
559
|
decorView.addView(overlay);
|
|
550
|
-
// Sizing updates are handled by the unified listener in
|
|
560
|
+
// Sizing updates are handled by the unified listener in
|
|
561
|
+
// ensureEdgeToEdgeConfigured
|
|
551
562
|
decorView.requestApplyInsets();
|
|
552
563
|
} else {
|
|
553
564
|
Log.d(TAG, "ensureStatusBarOverlay: updating existing overlay");
|
|
@@ -597,7 +608,8 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
597
608
|
overlay.setLayoutParams(lp);
|
|
598
609
|
|
|
599
610
|
decorView.addView(overlay);
|
|
600
|
-
// Sizing updates are handled by the unified listener in
|
|
611
|
+
// Sizing updates are handled by the unified listener in
|
|
612
|
+
// ensureEdgeToEdgeConfigured
|
|
601
613
|
decorView.requestApplyInsets();
|
|
602
614
|
} else {
|
|
603
615
|
Log.d(TAG, "ensureNavBarOverlay: updating existing overlay");
|
|
@@ -623,9 +635,9 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
623
635
|
}
|
|
624
636
|
|
|
625
637
|
private void applyWindowBackground(Activity activity, @ColorInt int color) {
|
|
626
|
-
Log.d(TAG, "applyWindowBackground:
|
|
638
|
+
Log.d(TAG, "applyWindowBackground: body is always transparent; status/nav bars use overlays/native APIs");
|
|
627
639
|
View decorView = activity.getWindow().getDecorView();
|
|
628
|
-
decorView.setBackgroundColor(
|
|
640
|
+
decorView.setBackgroundColor(Color.TRANSPARENT);
|
|
629
641
|
}
|
|
630
642
|
|
|
631
643
|
/**
|
|
@@ -637,8 +649,8 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
637
649
|
Window window = activity.getWindow();
|
|
638
650
|
ViewGroup decorView = (ViewGroup) window.getDecorView();
|
|
639
651
|
|
|
640
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.
|
|
641
|
-
//
|
|
652
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
653
|
+
// API 31+: edge-to-edge uses overlay views for both bars
|
|
642
654
|
View statusBarOverlay = decorView.findViewWithTag(STATUS_BAR_OVERLAY_TAG);
|
|
643
655
|
if (statusBarOverlay != null) {
|
|
644
656
|
statusBarOverlay.setBackgroundColor(Color.TRANSPARENT);
|
|
@@ -650,7 +662,7 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
650
662
|
Log.d(TAG, "makeStatusBarBackgroundTransparent: nav bar overlay made transparent");
|
|
651
663
|
}
|
|
652
664
|
} else {
|
|
653
|
-
// API 29–
|
|
665
|
+
// API 29–30: no edge-to-edge, native window API
|
|
654
666
|
window.setStatusBarColor(Color.TRANSPARENT);
|
|
655
667
|
window.setNavigationBarColor(Color.TRANSPARENT);
|
|
656
668
|
Log.d(TAG, "makeStatusBarBackgroundTransparent: set native bar colors to transparent");
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
package com.cap.plugins.statusbar;
|
|
2
2
|
|
|
3
|
-
import android.os.Build;
|
|
4
3
|
import android.view.View;
|
|
5
4
|
|
|
6
|
-
import androidx.core.graphics.Insets;
|
|
7
|
-
import androidx.core.view.ViewCompat;
|
|
8
|
-
import androidx.core.view.WindowInsetsCompat;
|
|
9
|
-
|
|
10
5
|
import com.getcapacitor.Plugin;
|
|
11
6
|
import com.getcapacitor.PluginCall;
|
|
12
7
|
import com.getcapacitor.PluginMethod;
|
|
@@ -19,21 +14,10 @@ public class CapacitorStatusBarPlugin extends Plugin {
|
|
|
19
14
|
@Override
|
|
20
15
|
public void load() {
|
|
21
16
|
super.load();
|
|
22
|
-
// Apply default style based on system theme on plugin load
|
|
23
17
|
getActivity().runOnUiThread(() -> {
|
|
24
|
-
|
|
18
|
+
View webView = getBridge().getWebView();
|
|
19
|
+
implementation.ensureEdgeToEdgeConfigured(getActivity(), webView);
|
|
25
20
|
implementation.applyDefaultStyle(getActivity());
|
|
26
|
-
|
|
27
|
-
// On Android 15+ (API 35+), edge-to-edge is enforced and the WebView content
|
|
28
|
-
// extends under system bars. Apply padding so Ionic content stays in the safe area.
|
|
29
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
|
30
|
-
View webView = getBridge().getWebView();
|
|
31
|
-
ViewCompat.setOnApplyWindowInsetsListener(webView, (v, insets) -> {
|
|
32
|
-
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
|
33
|
-
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
|
34
|
-
return insets;
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
21
|
});
|
|
38
22
|
}
|
|
39
23
|
|
|
@@ -71,7 +55,7 @@ public class CapacitorStatusBarPlugin extends Plugin {
|
|
|
71
55
|
public void hide(PluginCall call) {
|
|
72
56
|
try {
|
|
73
57
|
getActivity().runOnUiThread(() -> {
|
|
74
|
-
implementation.hideStatusBar(getActivity()
|
|
58
|
+
implementation.hideStatusBar(getActivity());
|
|
75
59
|
call.resolve();
|
|
76
60
|
});
|
|
77
61
|
} catch (Exception e) {
|
|
@@ -227,8 +227,8 @@ import Capacitor
|
|
|
227
227
|
return
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
window.backgroundColor =
|
|
231
|
-
print("CapacitorStatusBar: setBackground -
|
|
230
|
+
window.backgroundColor = .clear
|
|
231
|
+
print("CapacitorStatusBar: setBackground - Body is always transparent; status/nav bars use overlays/native APIs")
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
|
|
@@ -237,20 +237,15 @@ import Capacitor
|
|
|
237
237
|
var insets: [String: CGFloat] = ["top": 0, "bottom": 0, "left": 0, "right": 0]
|
|
238
238
|
|
|
239
239
|
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
|
240
|
-
let window = windowScene.windows.first {
|
|
241
|
-
// Use statusBarManager for accurate status bar height
|
|
242
|
-
let statusBarHeight = windowScene.statusBarManager?.statusBarFrame.height ?? 0
|
|
240
|
+
let window = windowScene.windows.first(where: { $0.isKeyWindow }) ?? windowScene.windows.first {
|
|
243
241
|
let safeAreaInsets = window.safeAreaInsets
|
|
244
242
|
|
|
245
|
-
|
|
246
|
-
insets["
|
|
247
|
-
|
|
248
|
-
insets["
|
|
249
|
-
// left/right: safe area for landscape / display cutouts
|
|
250
|
-
insets["left"] = safeAreaInsets.left
|
|
251
|
-
insets["right"] = safeAreaInsets.right
|
|
243
|
+
insets["top"] = self.sanitizedInsetValue(safeAreaInsets.top)
|
|
244
|
+
insets["bottom"] = 0
|
|
245
|
+
insets["left"] = 0
|
|
246
|
+
insets["right"] = 0
|
|
252
247
|
|
|
253
|
-
print("CapacitorStatusBar: getSafeAreaInsets - top=\(
|
|
248
|
+
print("CapacitorStatusBar: getSafeAreaInsets - top=\(safeAreaInsets.top), bottom=\(safeAreaInsets.bottom), left=\(safeAreaInsets.left), right=\(safeAreaInsets.right)")
|
|
254
249
|
} else {
|
|
255
250
|
print("CapacitorStatusBar: getSafeAreaInsets - Unable to get window, returning zero insets")
|
|
256
251
|
}
|
|
@@ -399,6 +394,12 @@ import Capacitor
|
|
|
399
394
|
return (0.299 * red + 0.587 * green + 0.114 * blue)
|
|
400
395
|
}
|
|
401
396
|
|
|
397
|
+
/// Guard against non-finite/negative inset values before bridging to JS.
|
|
398
|
+
private func sanitizedInsetValue(_ value: CGFloat) -> CGFloat {
|
|
399
|
+
guard value.isFinite else { return 0 }
|
|
400
|
+
return max(0, value)
|
|
401
|
+
}
|
|
402
|
+
|
|
402
403
|
private func isSystemInDarkMode() -> Bool {
|
|
403
404
|
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
|
404
405
|
let window = windowScene.windows.first else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "capacitor-plugin-status-bar",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.12",
|
|
4
4
|
"description": "Capacitor plugin for managing the status bar style, visibility, and color on iOS and Android. Control overlay modes, background colors, and appearance for native mobile applications.",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|