diff --git a/README.md b/README.md index 1082a1b..7bb1f8d 100644 --- a/README.md +++ b/README.md @@ -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(); diff --git a/src/android/StatusBar.java b/src/android/StatusBar.java index 7248906..b1d7be6 100644 --- a/src/android/StatusBar.java +++ b/src/android/StatusBar.java @@ -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; @@ -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"; @@ -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; @@ -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); }); } @@ -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; @@ -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; @@ -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; @@ -280,17 +263,21 @@ 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'"); } } } @@ -298,9 +285,23 @@ private void setStatusBarStyle(final String style) { @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; + } + } } diff --git a/src/ios/CDVStatusBar.m b/src/ios/CDVStatusBar.m index 5b4d86e..e24c97a 100644 --- a/src/ios/CDVStatusBar.m +++ b/src/ios/CDVStatusBar.m @@ -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"]) { diff --git a/tests/tests.js b/tests/tests.js index fc32d69..d5da135 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -87,7 +87,7 @@ exports.defineManualTests = function (contentEl, createActionButton) { StatusBar.styleDefault(); } - function doColor4() { + function doColor4 () { log('set style=darkcontent'); StatusBar.styleDarkContent(); } @@ -108,8 +108,6 @@ exports.defineManualTests = function (contentEl, createActionButton) { 'Expected result: Status bar will be visible' + '
' + 'Expected result: Status bar will be hidden' + - ' ' + - 'Expected result: Status bar text will be a light (white) color' + ' ' + 'Expected result: Status bar text will be a dark (black) color