Skip to content

Commit

Permalink
feat: default style is according device theme
Browse files Browse the repository at this point in the history
  • Loading branch information
andredestro committed Aug 9, 2024
1 parent 1c22c7f commit 2761a90
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 63 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ Quick Example
StatusBar.styleDefault
=================

Use the default statusbar (dark text, for light backgrounds).
For Android - Automatically chooses light or dark content based on the device theme.
For iOS - Automatically chooses light or dark content based on the user interface style.

StatusBar.styleDefault();
Expand Down
107 changes: 54 additions & 53 deletions src/android/StatusBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import android.content.res.Configuration;
import android.graphics.Color;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.Window;
Expand All @@ -46,8 +45,6 @@ public class StatusBar extends CordovaPlugin {
private static final String TAG = "StatusBar";
private static final String CORDOVA_STATIC_CHANNEL = "StatusBarStaticChannel";

private boolean doOverlay;

private static final String ACTION_HIDE = "hide";
private static final String ACTION_SHOW = "show";
private static final String ACTION_READY = "_ready";
Expand All @@ -63,6 +60,10 @@ public class StatusBar extends CordovaPlugin {
private static final String STYLE_LIGHT_CONTENT = "lightcontent";
private static final String STYLE_DARK_CONTENT = "darkcontent";

private boolean doOverlay;
private String currentStyle = "";
private String currentColor = "";

private AppCompatActivity activity;
private Window window;

Expand All @@ -82,49 +83,31 @@ public void initialize(final CordovaInterface cordova, CordovaWebView webView) {
window = activity.getWindow();
ActivityAssistant.getInstance().assistActivity(activity);

activity.runOnUiThread(new Runnable() {
@Override
public void run() {
doOverlay = preferences.getBoolean("StatusBarOverlaysWebView", false);

// Clear flag FLAG_FORCE_NOT_FULLSCREEN which is set initially
// by the Cordova.
window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
activity.runOnUiThread(() -> {
// Clear flag FLAG_FORCE_NOT_FULLSCREEN which is set initially
// by the Cordova.
window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

// Allows app to overlap cutout area from device when in landscape mode (same as iOS)
// More info: https://developer.android.com/reference/android/R.attr.html#windowLayoutInDisplayCutoutMode
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
window.getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
}
// Read 'StatusBarOverlaysWebView' from config.xml, default is true.
doOverlay = preferences.getBoolean("StatusBarOverlaysWebView", true);
setStatusBarTransparent(doOverlay);

// Added to override logic if plugin is installed in OutSystems Now app.
boolean isOutSystemsNow = preferences.getBoolean("IsOutSystemsNow", false);

if(isOutSystemsNow || (doOverlay && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)){
// Read 'StatusBarOverlaysWebView' from config.xml, and if the value is true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setStatusBarTransparent(doOverlay);
}
else if(Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
else{
LOG.e(TAG, "Translucent status bar not supported in your Android version");
}
// Read 'StatusBarBackgroundColor' from config.xml, default is #000000.
currentColor = preferences.getString("StatusBarBackgroundColor", "#000000");

ActivityAssistant.getInstance().applyGlobalLayoutListener();
} else {
// Read 'StatusBarBackgroundColor' from config.xml, default is #000000.
setStatusBarBackgroundColor(preferences.getString("StatusBarBackgroundColor", "#000000"));
// Added to override logic if plugin is installed in OutSystems Now app.
boolean isOutSystemsNow = preferences.getBoolean("IsOutSystemsNow", false);

// Read 'StatusBarStyle' from config.xml, default is 'lightcontent'.
String styleSetting = preferences.getString("StatusBarStyle", "lightcontent");
if (styleSetting.equalsIgnoreCase("blacktranslucent") || styleSetting.equalsIgnoreCase("blackopaque")) {
LOG.w(TAG, styleSetting +" is deprecated and will be removed in next major release, use lightcontent");
}
setStatusBarStyle(styleSetting);
}
if (isOutSystemsNow || doOverlay) {
ActivityAssistant.getInstance().applyGlobalLayoutListener();
} else {
// Read 'StatusBarBackgroundColor' from config.xml, default is #000000.
setStatusBarBackgroundColor(currentColor);
}

// Read 'StatusBarStyle' from config.xml, default is 'default'.
String styleSetting = preferences.getString("StatusBarStyle", STYLE_DEFAULT);
setStatusBarStyle(styleSetting);
});
}

Expand Down Expand Up @@ -203,6 +186,8 @@ public boolean execute(final String action, final CordovaArgs args, final Callba

if (doOverlay) {
ActivityAssistant.getInstance().applyGlobalLayoutListener();
} else {
setStatusBarBackgroundColor(currentColor);
}
});
return true;
Expand Down Expand Up @@ -233,7 +218,6 @@ public boolean execute(final String action, final CordovaArgs args, final Callba
return false;
}

// Only used with API 21+
private void setStatusBarBackgroundColor(final String colorPref) {
if (colorPref.isEmpty()) return;

Expand All @@ -248,27 +232,26 @@ private void setStatusBarBackgroundColor(final String colorPref) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // SDK 19-30
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); // SDK 21
window.setStatusBarColor(color);
currentColor = colorPref;
}

// A method to find height of the status bar
public int getStatusBarHeight() {

int statusbarHeight = 0;
int resourceId = this.cordova.getActivity().getApplicationContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
int resourceId = activity.getApplicationContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusbarHeight = (int)this.cordova.getActivity().getApplicationContext().getResources().getDimension(resourceId);
statusbarHeight = (int)activity.getApplicationContext().getResources().getDimension(resourceId);
}

DisplayMetrics metrics = this.cordova.getActivity().getApplicationContext().getResources().getDisplayMetrics();
DisplayMetrics metrics = activity.getApplicationContext().getResources().getDisplayMetrics();
float densityDpi = metrics.density;

int result = (int)(statusbarHeight / densityDpi);

return result;
return (int)(statusbarHeight / densityDpi);
}

private void setStatusBarTransparent(final boolean isTransparent) {
final Window window = cordova.getActivity().getWindow();

int visibility = isTransparent
? View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
: View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE;
Expand All @@ -280,27 +263,45 @@ private void setStatusBarTransparent(final boolean isTransparent) {
}
}

private void setStatusBarStyle(final String style) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !style.isEmpty()) {
private void setStatusBarStyle(String style) {
if (!style.isEmpty()) {
this.currentStyle = style;
View decorView = window.getDecorView();
WindowInsetsControllerCompat windowInsetsControllerCompat = WindowCompat.getInsetsController(window, decorView);

if (style.equals(STYLE_DEFAULT) || style.equals(STYLE_DARK_CONTENT)) {
if (style.equals(STYLE_DEFAULT)) {
style = getStyleFromDeviceTheme();
}
if (style.equals(STYLE_DARK_CONTENT)) {
windowInsetsControllerCompat.setAppearanceLightStatusBars(true);
} else if (style.equals(STYLE_LIGHT_CONTENT)) {
windowInsetsControllerCompat.setAppearanceLightStatusBars(false);
} else {
LOG.e(TAG, "Invalid style, must be either 'default' or 'lightcontent'");
LOG.e(TAG, "Invalid style, must be either 'default', 'lightcontent' or 'darkcontent'");
}
}
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (this.currentStyle.equals(STYLE_DEFAULT))
setStatusBarStyle(STYLE_DEFAULT);
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
pluginResult.setKeepCallback(true);
webView.sendPluginResult(pluginResult, CORDOVA_STATIC_CHANNEL);
}

private String getStyleFromDeviceTheme() {
int nightModeFlags = cordova.getContext().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
switch (nightModeFlags) {
case Configuration.UI_MODE_NIGHT_YES:
case Configuration.UI_MODE_NIGHT_UNDEFINED:
default:
return STYLE_LIGHT_CONTENT;

case Configuration.UI_MODE_NIGHT_NO:
return STYLE_DARK_CONTENT;
}
}
}
2 changes: 1 addition & 1 deletion src/ios/CDVStatusBar.m
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ - (void) setStyleForStatusBar:(UIStatusBarStyle)style

- (void) setStatusBarStyle:(NSString*)statusBarStyle
{
// default, lightContent
// default, lightContent, darkContent
NSString* lcStatusBarStyle = [statusBarStyle lowercaseString];

if ([lcStatusBarStyle isEqualToString:@"default"]) {
Expand Down
8 changes: 3 additions & 5 deletions tests/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
StatusBar.styleDefault();
}

function doColor4() {
function doColor4 () {
log('set style=darkcontent');
StatusBar.styleDarkContent();
}
Expand All @@ -108,8 +108,6 @@ exports.defineManualTests = function (contentEl, createActionButton) {
'Expected result: Status bar will be visible' +
'</p> <div id="action-hide"></div>' +
'Expected result: Status bar will be hidden' +
'</p> <div id="action-color2"></div>' +
'Expected result: Status bar text will be a light (white) color' +
'</p> <div id="action-color3"></div>' +
'Expected result: Status bar text will be a dark (black) color<br>for iOS - a device theme depending (black or white) color' +
'</p> <div id="action-color4"></div>' +
Expand Down Expand Up @@ -164,10 +162,10 @@ exports.defineManualTests = function (contentEl, createActionButton) {
'Style=dark',
function () {
doColor4();
},
},
'action-color4'
);

createActionButton(
'Toggle Overlays',
function () {
Expand Down
3 changes: 2 additions & 1 deletion types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ interface StatusBar {
overlaysWebView(isOverlay: boolean): void;

/**
* Use the darkContent statusbar (dark text, for light backgrounds and on iOS automatically chooses light or dark content based on the user interface style)
* On Android automatically chooses light or dark content based on the device theme
* and on iOS automatically chooses light or dark content based on the user interface style
*/
styleDefault(): void;

Expand Down
7 changes: 5 additions & 2 deletions www/statusbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,18 @@ var StatusBar = {
},

styleDefault: function () {
// dark text ( to be used on a light background and on iOS automatically chooses light or dark content based on the user interface style)
/*
* On Android automatically chooses light or dark content based on the device theme
* and on iOS automatically chooses light or dark content based on the user interface style
*/
exec(null, null, 'StatusBar', 'styleDefault', []);
},

styleLightContent: function () {
// light text ( to be used on a dark background )
exec(null, null, 'StatusBar', 'styleLightContent', []);
},

styleDarkContent: function () {
// dark text ( to be used on a light background )
exec(null, null, 'StatusBar', 'styleDarkContent', []);
Expand Down

0 comments on commit 2761a90

Please sign in to comment.