capacitor-plugin-status-bar 2.0.10 → 2.0.11
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,9 +41,11 @@ 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
51
|
* Ensures edge-to-edge is properly configured for Android 15+.
|
|
@@ -59,12 +60,15 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
59
60
|
|
|
60
61
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
61
62
|
// Android 12+ (API 31+): enable edge-to-edge layout.
|
|
62
|
-
// The nav bar uses overlay views because gesture navigation ignores
|
|
63
|
+
// The nav bar uses overlay views because gesture navigation ignores
|
|
64
|
+
// setNavigationBarColor().
|
|
63
65
|
// 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
|
|
66
|
+
// overlay is only needed on API 35+ where edge-to-edge is enforced and the
|
|
67
|
+
// native API is a no-op.
|
|
65
68
|
WindowCompat.setDecorFitsSystemWindows(window, false);
|
|
66
69
|
|
|
67
|
-
// Set a transparent baseline; setStyle() will apply the actual color via
|
|
70
|
+
// Set a transparent baseline; setStyle() will apply the actual color via
|
|
71
|
+
// setStatusBarColor()
|
|
68
72
|
// (API 31-34) or the status bar overlay (API 35+).
|
|
69
73
|
window.setStatusBarColor(Color.TRANSPARENT);
|
|
70
74
|
window.setNavigationBarColor(Color.TRANSPARENT);
|
|
@@ -104,8 +108,10 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
104
108
|
Log.d(TAG, "ensureEdgeToEdgeConfigured: edge-to-edge with overlay views, API=" + Build.VERSION.SDK_INT);
|
|
105
109
|
} else {
|
|
106
110
|
// Android < 12 (API < 31): Only disable contrast enforcement.
|
|
107
|
-
// Do NOT call setDecorFitsSystemWindows(false), create overlay views, or set
|
|
108
|
-
//
|
|
111
|
+
// Do NOT call setDecorFitsSystemWindows(false), create overlay views, or set
|
|
112
|
+
// insets listener.
|
|
113
|
+
// This avoids conflicts with plugins like
|
|
114
|
+
// @capawesome/capacitor-android-edge-to-edge-support.
|
|
109
115
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
110
116
|
window.setStatusBarContrastEnforced(false);
|
|
111
117
|
window.setNavigationBarContrastEnforced(false);
|
|
@@ -157,57 +163,42 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
157
163
|
showNavigationBar(activity, true);
|
|
158
164
|
}
|
|
159
165
|
|
|
160
|
-
public void hideStatusBar(Activity activity
|
|
161
|
-
Log.d(TAG, "hideStatusBar: animation=" + animation + ", API=" + Build.VERSION.SDK_INT);
|
|
166
|
+
public void hideStatusBar(Activity activity) {
|
|
162
167
|
Window window = activity.getWindow();
|
|
163
168
|
View decorView = window.getDecorView();
|
|
164
169
|
|
|
165
|
-
|
|
170
|
+
// Slide mode: Hide status bar and navigation bar completely (current behavior)
|
|
171
|
+
Log.d(TAG, "hideStatusBar: slide mode - hiding bars completely");
|
|
166
172
|
|
|
167
|
-
if (
|
|
168
|
-
//
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
178
|
-
// API 30+ (Android 11+) - Use WindowInsetsController
|
|
179
|
-
WindowInsetsController controller = window.getInsetsController();
|
|
180
|
-
if (controller != null) {
|
|
181
|
-
Log.d(TAG, "hideStatusBar: hiding system bars (API 30+)");
|
|
182
|
-
// Hide both status and navigation bars together
|
|
183
|
-
controller.hide(WindowInsets.Type.systemBars());
|
|
184
|
-
// Set behavior for immersive mode (user can swipe to reveal temporarily)
|
|
185
|
-
controller.setSystemBarsBehavior(
|
|
186
|
-
WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
|
187
|
-
} else {
|
|
188
|
-
Log.w(TAG, "hideStatusBar: WindowInsetsController is null");
|
|
189
|
-
}
|
|
173
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
174
|
+
// API 30+ (Android 11+) - Use WindowInsetsController
|
|
175
|
+
WindowInsetsController controller = window.getInsetsController();
|
|
176
|
+
if (controller != null) {
|
|
177
|
+
Log.d(TAG, "hideStatusBar: hiding system bars (API 30+)");
|
|
178
|
+
// Hide both status and navigation bars together
|
|
179
|
+
controller.hide(WindowInsets.Type.systemBars());
|
|
180
|
+
// Set behavior for immersive mode (user can swipe to reveal temporarily)
|
|
181
|
+
controller.setSystemBarsBehavior(
|
|
182
|
+
WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
|
190
183
|
} 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);
|
|
184
|
+
Log.w(TAG, "hideStatusBar: WindowInsetsController is null");
|
|
202
185
|
}
|
|
203
|
-
|
|
204
|
-
// Make the overlay backgrounds transparent so content shows through
|
|
205
|
-
makeStatusBarBackgroundTransparent(activity);
|
|
206
186
|
} else {
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
|
|
187
|
+
// API 29 (Android 10) - Use system UI visibility flags (deprecated but
|
|
188
|
+
// necessary)
|
|
189
|
+
Log.d(TAG, "hideStatusBar: hiding using system UI flags (API 29)");
|
|
190
|
+
// Use immersive sticky mode with proper layout flags for Android 10
|
|
191
|
+
decorView.setSystemUiVisibility(
|
|
192
|
+
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
|
193
|
+
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
|
194
|
+
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
|
195
|
+
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
|
196
|
+
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
|
197
|
+
| View.SYSTEM_UI_FLAG_FULLSCREEN);
|
|
210
198
|
}
|
|
199
|
+
|
|
200
|
+
// Make the overlay backgrounds transparent so content shows through
|
|
201
|
+
makeStatusBarBackgroundTransparent(activity);
|
|
211
202
|
}
|
|
212
203
|
|
|
213
204
|
public void setStyle(Activity activity, String style, @Nullable String colorHex) {
|
|
@@ -262,7 +253,8 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
262
253
|
}
|
|
263
254
|
|
|
264
255
|
// Set icon appearance AFTER background operations.
|
|
265
|
-
// On Android 13 (API 33), applyStatusBarBackground triggers
|
|
256
|
+
// On Android 13 (API 33), applyStatusBarBackground triggers
|
|
257
|
+
// requestApplyInsets()
|
|
266
258
|
// which causes the WindowInsetsController to reset setSystemBarsAppearance.
|
|
267
259
|
// Calling setLightStatusBarIcons last ensures the icon style is not overridden.
|
|
268
260
|
setLightStatusBarIcons(window, lightBackground);
|
|
@@ -291,7 +283,8 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
291
283
|
* Returns the insets for status bar, navigation bar, and notch areas.
|
|
292
284
|
*
|
|
293
285
|
* @param activity The activity to get the insets from
|
|
294
|
-
* @return A map containing top, bottom, left, and right inset values in dp
|
|
286
|
+
* @return A map containing top, bottom, left, and right inset values in dp
|
|
287
|
+
* (density-independent pixels)
|
|
295
288
|
*/
|
|
296
289
|
public java.util.Map<String, Integer> getSafeAreaInsets(Activity activity) {
|
|
297
290
|
Log.d(TAG, "getSafeAreaInsets");
|
|
@@ -302,10 +295,12 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
302
295
|
WindowInsetsCompat windowInsets = ViewCompat.getRootWindowInsets(decorView);
|
|
303
296
|
|
|
304
297
|
if (windowInsets != null) {
|
|
305
|
-
// Use WindowInsetsCompat for accurate, type-specific insets across all API
|
|
298
|
+
// Use WindowInsetsCompat for accurate, type-specific insets across all API
|
|
299
|
+
// levels
|
|
306
300
|
androidx.core.graphics.Insets statusBars = windowInsets.getInsets(WindowInsetsCompat.Type.statusBars());
|
|
307
301
|
androidx.core.graphics.Insets navBars = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars());
|
|
308
|
-
androidx.core.graphics.Insets displayCutout = windowInsets
|
|
302
|
+
androidx.core.graphics.Insets displayCutout = windowInsets
|
|
303
|
+
.getInsets(WindowInsetsCompat.Type.displayCutout());
|
|
309
304
|
|
|
310
305
|
int topPx = Math.max(statusBars.top, displayCutout.top);
|
|
311
306
|
int bottomPx = Math.max(navBars.bottom, displayCutout.bottom);
|
|
@@ -500,11 +495,14 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
500
495
|
private void applyStatusBarBackground(Activity activity, @ColorInt int color) {
|
|
501
496
|
Log.d(TAG, "applyStatusBarBackground: color=#" + Integer.toHexString(color) + ", API=" + Build.VERSION.SDK_INT);
|
|
502
497
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
|
503
|
-
// Android 15+ (API 35+): edge-to-edge is enforced, setStatusBarColor() is a
|
|
498
|
+
// Android 15+ (API 35+): edge-to-edge is enforced, setStatusBarColor() is a
|
|
499
|
+
// no-op
|
|
504
500
|
ensureStatusBarOverlay(activity, color);
|
|
505
501
|
} else {
|
|
506
|
-
// API 29–34: setStatusBarColor() works reliably for the status bar on all
|
|
507
|
-
//
|
|
502
|
+
// API 29–34: setStatusBarColor() works reliably for the status bar on all
|
|
503
|
+
// navigation modes.
|
|
504
|
+
// Note: gesture navigation only ignores setNavigationBarColor(), not
|
|
505
|
+
// setStatusBarColor().
|
|
508
506
|
activity.getWindow().setStatusBarColor(color);
|
|
509
507
|
}
|
|
510
508
|
}
|
|
@@ -513,11 +511,13 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
513
511
|
Log.d(TAG, "applyNavigationBarBackground: color=#" + Integer.toHexString(color) + ", API="
|
|
514
512
|
+ Build.VERSION.SDK_INT);
|
|
515
513
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
|
516
|
-
// Android 15+ (API 35+): edge-to-edge enforced, setNavigationBarColor() is a
|
|
514
|
+
// Android 15+ (API 35+): edge-to-edge enforced, setNavigationBarColor() is a
|
|
515
|
+
// no-op
|
|
517
516
|
ensureNavBarOverlay(activity, color);
|
|
518
517
|
} else {
|
|
519
518
|
// API 29–34: setNavigationBarColor() works for button navigation.
|
|
520
|
-
// Gesture navigation ignores it (system enforces transparency for gesture
|
|
519
|
+
// Gesture navigation ignores it (system enforces transparency for gesture
|
|
520
|
+
// handles),
|
|
521
521
|
// but in that case there is no visible nav bar to color anyway.
|
|
522
522
|
activity.getWindow().setNavigationBarColor(color);
|
|
523
523
|
}
|
|
@@ -547,7 +547,8 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
547
547
|
overlay.setLayoutParams(lp);
|
|
548
548
|
|
|
549
549
|
decorView.addView(overlay);
|
|
550
|
-
// Sizing updates are handled by the unified listener in
|
|
550
|
+
// Sizing updates are handled by the unified listener in
|
|
551
|
+
// ensureEdgeToEdgeConfigured
|
|
551
552
|
decorView.requestApplyInsets();
|
|
552
553
|
} else {
|
|
553
554
|
Log.d(TAG, "ensureStatusBarOverlay: updating existing overlay");
|
|
@@ -597,7 +598,8 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
597
598
|
overlay.setLayoutParams(lp);
|
|
598
599
|
|
|
599
600
|
decorView.addView(overlay);
|
|
600
|
-
// Sizing updates are handled by the unified listener in
|
|
601
|
+
// Sizing updates are handled by the unified listener in
|
|
602
|
+
// ensureEdgeToEdgeConfigured
|
|
601
603
|
decorView.requestApplyInsets();
|
|
602
604
|
} else {
|
|
603
605
|
Log.d(TAG, "ensureNavBarOverlay: updating existing overlay");
|
|
@@ -623,9 +625,9 @@ public class CapacitorStatusBar extends Plugin {
|
|
|
623
625
|
}
|
|
624
626
|
|
|
625
627
|
private void applyWindowBackground(Activity activity, @ColorInt int color) {
|
|
626
|
-
Log.d(TAG, "applyWindowBackground:
|
|
628
|
+
Log.d(TAG, "applyWindowBackground: body is always transparent; status/nav bars use overlays/native APIs");
|
|
627
629
|
View decorView = activity.getWindow().getDecorView();
|
|
628
|
-
decorView.setBackgroundColor(
|
|
630
|
+
decorView.setBackgroundColor(Color.TRANSPARENT);
|
|
629
631
|
}
|
|
630
632
|
|
|
631
633
|
/**
|
|
@@ -71,7 +71,7 @@ public class CapacitorStatusBarPlugin extends Plugin {
|
|
|
71
71
|
public void hide(PluginCall call) {
|
|
72
72
|
try {
|
|
73
73
|
getActivity().runOnUiThread(() -> {
|
|
74
|
-
implementation.hideStatusBar(getActivity()
|
|
74
|
+
implementation.hideStatusBar(getActivity());
|
|
75
75
|
call.resolve();
|
|
76
76
|
});
|
|
77
77
|
} 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.11",
|
|
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",
|