Skip to content

Commit 88228ac

Browse files
authored
feat(statusbar)!: implement overlay and background color in iOS (#2179)
1 parent 4fa3245 commit 88228ac

File tree

13 files changed

+547
-95
lines changed

13 files changed

+547
-95
lines changed

status-bar/README.md

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ The status bar visibility defaults to visible and the style defaults to
2020
`Style.Default`. You can change these defaults by adding
2121
`UIStatusBarHidden` and/or `UIStatusBarStyle` in `Info.plist`.
2222

23-
`setBackgroundColor` and `setOverlaysWebView` are currently not supported on
24-
iOS devices.
25-
2623
## Example
2724

2825
```typescript
@@ -33,7 +30,7 @@ window.addEventListener('statusTap', function () {
3330
console.log('statusbar tapped');
3431
});
3532

36-
// Display content under transparent status bar (Android only)
33+
// Display content under transparent status bar
3734
StatusBar.setOverlaysWebView({ overlay: true });
3835

3936
const setStatusBarStyleDark = async () => {
@@ -53,6 +50,57 @@ const showStatusBar = async () => {
5350
};
5451
```
5552

53+
## Configuration
54+
55+
<docgen-config>
56+
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
57+
58+
These config values are available:
59+
60+
| Prop | Type | Description | Default | Since |
61+
| --------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------- | -------------------- | ----- |
62+
| **`overlaysWebView`** | <code>boolean</code> | Whether the statusbar is overlaid or not. | <code>true</code> | 1.0.0 |
63+
| **`style`** | <code>string</code> | <a href="#style">Style</a> of the text of the status bar. | <code>default</code> | 1.0.0 |
64+
| **`backgroundColor`** | <code>string</code> | Color of the background of the statusbar in hex format, #RRGGBB. Doesn't work if `overlaysWebView` is true. | <code>#000000</code> | 1.0.0 |
65+
66+
### Examples
67+
68+
In `capacitor.config.json`:
69+
70+
```json
71+
{
72+
"plugins": {
73+
"StatusBar": {
74+
"overlaysWebView": false,
75+
"style": "DARK",
76+
"backgroundColor": "#ffffffff"
77+
}
78+
}
79+
}
80+
```
81+
82+
In `capacitor.config.ts`:
83+
84+
```ts
85+
/// <reference types="@capacitor/status-bar" />
86+
87+
import { CapacitorConfig } from '@capacitor/cli';
88+
89+
const config: CapacitorConfig = {
90+
plugins: {
91+
StatusBar: {
92+
overlaysWebView: false,
93+
style: "DARK",
94+
backgroundColor: "#ffffffff",
95+
},
96+
},
97+
};
98+
99+
export default config;
100+
```
101+
102+
</docgen-config>
103+
56104
## API
57105

58106
<docgen-index>
@@ -96,8 +144,6 @@ setBackgroundColor(options: BackgroundColorOptions) => Promise<void>
96144

97145
Set the background color of the status bar.
98146

99-
This method is only supported on Android.
100-
101147
| Param | Type |
102148
| ------------- | ------------------------------------------------------------------------- |
103149
| **`options`** | <code><a href="#backgroundcoloroptions">BackgroundColorOptions</a></code> |
@@ -169,8 +215,6 @@ setOverlaysWebView(options: SetOverlaysWebViewOptions) => Promise<void>
169215
Set whether or not the status bar should overlay the webview to allow usage
170216
of the space underneath it.
171217

172-
This method is only supported on Android.
173-
174218
| Param | Type |
175219
| ------------- | ------------------------------------------------------------------------------- |
176220
| **`options`** | <code><a href="#setoverlayswebviewoptions">SetOverlaysWebViewOptions</a></code> |
@@ -192,9 +236,9 @@ This method is only supported on Android.
192236

193237
#### BackgroundColorOptions
194238

195-
| Prop | Type | Description | Since |
196-
| ----------- | ------------------- | ------------------------------------------------------------------------------------------- | ----- |
197-
| **`color`** | <code>string</code> | A hex color to which the status bar color is set. This option is only supported on Android. | 1.0.0 |
239+
| Prop | Type | Description | Since |
240+
| ----------- | ------------------- | ------------------------------------------------- | ----- |
241+
| **`color`** | <code>string</code> | A hex color to which the status bar color is set. | 1.0.0 |
198242

199243

200244
#### AnimationOptions
@@ -206,12 +250,12 @@ This method is only supported on Android.
206250

207251
#### StatusBarInfo
208252

209-
| Prop | Type | Description | Since |
210-
| -------------- | --------------------------------------- | ----------------------------------------------------------------------------------- | ----- |
211-
| **`visible`** | <code>boolean</code> | Whether the status bar is visible or not. | 1.0.0 |
212-
| **`style`** | <code><a href="#style">Style</a></code> | The current status bar style. | 1.0.0 |
213-
| **`color`** | <code>string</code> | The current status bar color. This option is only supported on Android. | 1.0.0 |
214-
| **`overlays`** | <code>boolean</code> | Whether the statusbar is overlaid or not. This option is only supported on Android. | 1.0.0 |
253+
| Prop | Type | Description | Since |
254+
| -------------- | --------------------------------------- | ----------------------------------------- | ----- |
255+
| **`visible`** | <code>boolean</code> | Whether the status bar is visible or not. | 1.0.0 |
256+
| **`style`** | <code><a href="#style">Style</a></code> | The current status bar style. | 1.0.0 |
257+
| **`color`** | <code>string</code> | The current status bar color. | 1.0.0 |
258+
| **`overlays`** | <code>boolean</code> | Whether the statusbar is overlaid or not. | 1.0.0 |
215259

216260

217261
#### SetOverlaysWebViewOptions

status-bar/android/src/main/java/com/capacitorjs/plugins/statusbar/StatusBar.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.capacitorjs.plugins.statusbar;
22

33
import android.graphics.Color;
4+
import android.util.DisplayMetrics;
45
import android.view.View;
56
import android.view.Window;
67
import android.view.WindowManager;
@@ -16,11 +17,15 @@ public class StatusBar {
1617
private final AppCompatActivity activity;
1718
private final String defaultStyle;
1819

19-
public StatusBar(AppCompatActivity activity) {
20+
public StatusBar(AppCompatActivity activity, StatusBarConfig config) {
2021
// save initial color of the status bar
2122
this.activity = activity;
2223
this.currentStatusBarColor = activity.getWindow().getStatusBarColor();
2324
this.defaultStyle = getStyle();
25+
26+
setBackgroundColor(config.getBackgroundColor());
27+
setStyle(config.getStyle());
28+
setOverlaysWebView(config.isOverlaysWebView());
2429
}
2530

2631
public void setStyle(String style) {
@@ -93,6 +98,7 @@ public StatusBarInfo getInfo() {
9398
info.setOverlays(getIsOverlaid());
9499
info.setVisible(isVisible);
95100
info.setColor(String.format("#%06X", (0xFFFFFF & window.getStatusBarColor())));
101+
info.setHeight(getStatusBarHeight());
96102
return info;
97103
}
98104

@@ -105,4 +111,17 @@ private String getStyle() {
105111
}
106112
return style;
107113
}
114+
115+
private int getStatusBarHeight() {
116+
int statusbarHeight = 0;
117+
int resourceId = activity.getApplicationContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
118+
if (resourceId > 0) {
119+
statusbarHeight = (int) activity.getApplicationContext().getResources().getDimension(resourceId);
120+
}
121+
122+
DisplayMetrics metrics = activity.getApplicationContext().getResources().getDisplayMetrics();
123+
float densityDpi = metrics.density;
124+
125+
return (int) (statusbarHeight / densityDpi);
126+
}
108127
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.capacitorjs.plugins.statusbar;
2+
3+
import com.getcapacitor.util.WebColor;
4+
5+
public class StatusBarConfig {
6+
7+
private boolean overlaysWebView = true;
8+
private Integer backgroundColor = WebColor.parseColor("#000000");
9+
private String style = "DEFAULT";
10+
11+
public boolean isOverlaysWebView() {
12+
return overlaysWebView;
13+
}
14+
15+
public void setOverlaysWebView(boolean overlaysWebView) {
16+
this.overlaysWebView = overlaysWebView;
17+
}
18+
19+
public Integer getBackgroundColor() {
20+
return backgroundColor;
21+
}
22+
23+
public void setBackgroundColor(Integer backgroundColor) {
24+
this.backgroundColor = backgroundColor;
25+
}
26+
27+
public String getStyle() {
28+
return style;
29+
}
30+
31+
public void setStyle(String style) {
32+
this.style = style;
33+
}
34+
}

status-bar/android/src/main/java/com/capacitorjs/plugins/statusbar/StatusBarInfo.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package com.capacitorjs.plugins.statusbar;
22

3-
public class StatusBarInfo {
3+
import java.io.Serializable;
4+
5+
public class StatusBarInfo implements Serializable {
46

57
private boolean overlays;
68
private boolean visible;
79
private String style;
810
private String color;
11+
private int height;
912

1013
public boolean isOverlays() {
1114
return overlays;
@@ -38,4 +41,12 @@ public String getColor() {
3841
public void setColor(String color) {
3942
this.color = color;
4043
}
44+
45+
public int getHeight() {
46+
return height;
47+
}
48+
49+
public void setHeight(int height) {
50+
this.height = height;
51+
}
4152
}

status-bar/android/src/main/java/com/capacitorjs/plugins/statusbar/StatusBarPlugin.java

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.capacitorjs.plugins.statusbar;
22

33
import com.getcapacitor.JSObject;
4+
import com.getcapacitor.Logger;
45
import com.getcapacitor.Plugin;
56
import com.getcapacitor.PluginCall;
67
import com.getcapacitor.PluginMethod;
@@ -11,11 +12,44 @@
1112
@CapacitorPlugin(name = "StatusBar")
1213
public class StatusBarPlugin extends Plugin {
1314

15+
public static final String statusBarVisibilityChanged = "statusBarVisibilityChanged";
16+
public static final String statusBarOverlayChanged = "statusBarOverlayChanged";
17+
1418
private StatusBar implementation;
1519

1620
@Override
1721
public void load() {
18-
implementation = new StatusBar(getActivity());
22+
StatusBarConfig config = getStatusBarConfig();
23+
implementation = new StatusBar(getActivity(), config);
24+
}
25+
26+
private StatusBarConfig getStatusBarConfig() {
27+
StatusBarConfig config = new StatusBarConfig();
28+
String backgroundColor = getConfig().getString("backgroundColor");
29+
if (backgroundColor != null) {
30+
try {
31+
config.setBackgroundColor(WebColor.parseColor(backgroundColor));
32+
} catch (IllegalArgumentException ex) {
33+
Logger.debug("Background color not applied");
34+
}
35+
}
36+
config.setStyle(styleFromConfig(getConfig().getString("style", config.getStyle())));
37+
config.setOverlaysWebView(getConfig().getBoolean("overlaysWebView", config.isOverlaysWebView()));
38+
return config;
39+
}
40+
41+
private String styleFromConfig(String style) {
42+
switch (style.toLowerCase()) {
43+
case "lightcontent":
44+
case "dark":
45+
return "DARK";
46+
case "darkcontent":
47+
case "light":
48+
return "LIGHT";
49+
case "default":
50+
default:
51+
return "DEFAULT";
52+
}
1953
}
2054

2155
@PluginMethod
@@ -64,6 +98,8 @@ public void hide(final PluginCall call) {
6498
.executeOnMainThread(
6599
() -> {
66100
implementation.hide();
101+
StatusBarInfo info = implementation.getInfo();
102+
notifyListeners(statusBarVisibilityChanged, toJSObject(info));
67103
call.resolve();
68104
}
69105
);
@@ -76,6 +112,8 @@ public void show(final PluginCall call) {
76112
.executeOnMainThread(
77113
() -> {
78114
implementation.show();
115+
StatusBarInfo info = implementation.getInfo();
116+
notifyListeners(statusBarVisibilityChanged, toJSObject(info));
79117
call.resolve();
80118
}
81119
);
@@ -84,13 +122,7 @@ public void show(final PluginCall call) {
84122
@PluginMethod
85123
public void getInfo(final PluginCall call) {
86124
StatusBarInfo info = implementation.getInfo();
87-
88-
JSObject data = new JSObject();
89-
data.put("visible", info.isVisible());
90-
data.put("style", info.getStyle());
91-
data.put("color", info.getColor());
92-
data.put("overlays", info.isOverlays());
93-
call.resolve(data);
125+
call.resolve(toJSObject(info));
94126
}
95127

96128
@PluginMethod
@@ -100,8 +132,20 @@ public void setOverlaysWebView(final PluginCall call) {
100132
.executeOnMainThread(
101133
() -> {
102134
implementation.setOverlaysWebView(overlays);
135+
StatusBarInfo info = implementation.getInfo();
136+
notifyListeners(statusBarOverlayChanged, toJSObject(info));
103137
call.resolve();
104138
}
105139
);
106140
}
141+
142+
private JSObject toJSObject(StatusBarInfo info) {
143+
JSObject data = new JSObject();
144+
data.put("visible", info.isVisible());
145+
data.put("style", info.getStyle());
146+
data.put("color", info.getColor());
147+
data.put("overlays", info.isOverlays());
148+
data.put("height", info.getHeight());
149+
return data;
150+
}
107151
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Capacitor
2+
3+
extension CAPBridgeViewController {
4+
5+
open override func viewDidAppear(_ animated: Bool) {
6+
super.viewDidAppear(animated)
7+
NotificationCenter.default.post(Notification(name: .capacitorViewDidAppear))
8+
}
9+
10+
open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
11+
super.viewWillTransition(to: size, with: coordinator)
12+
NotificationCenter.default.post(Notification(name: .capacitorViewWillTransition))
13+
}
14+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import Capacitor
2+
3+
extension Notification.Name {
4+
public static let capacitorViewDidAppear = Notification.Name(rawValue: "CapacitorViewDidAppear")
5+
public static let capacitorViewWillTransition = Notification.Name(rawValue: "CapacitorViewWillTransition")
6+
}

0 commit comments

Comments
 (0)