summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormvglasow <michael -at- vonglasow.com>2019-02-06 02:01:56 +0100
committermvglasow <michael -at- vonglasow.com>2019-02-06 02:01:56 +0100
commit70002f725360c16dfa9ec20b285140d218de40d8 (patch)
tree9287c9858d97853cf861bd938a368e690e071c84
parent20a2846140ea111dfffe93d61bade915c85e933f (diff)
downloadnavit-70002f725360c16dfa9ec20b285140d218de40d8.tar.gz
Fix:port/android:Improve behavior of transparent system bars on API 23+
Signed-off-by: mvglasow <michael -at- vonglasow.com>
-rw-r--r--navit/android/src/org/navitproject/navit/Navit.java26
-rw-r--r--navit/android/src/org/navitproject/navit/NavitGraphics.java235
2 files changed, 159 insertions, 102 deletions
diff --git a/navit/android/src/org/navitproject/navit/Navit.java b/navit/android/src/org/navitproject/navit/Navit.java
index de7f25f4d..fb10d56dd 100644
--- a/navit/android/src/org/navitproject/navit/Navit.java
+++ b/navit/android/src/org/navitproject/navit/Navit.java
@@ -20,6 +20,7 @@
package org.navitproject.navit;
import android.Manifest;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -75,11 +76,6 @@ public class Navit extends Activity {
private NavitActivityResult[] ActivityResults;
public static InputMethodManager mgr = null;
public static DisplayMetrics metrics = null;
- public static int status_bar_height = 0;
- private static int action_bar_default_height = 0;
- public static int navigation_bar_height = 0;
- public static int navigation_bar_height_landscape = 0;
- public static int navigation_bar_width = 0;
public static Boolean show_soft_keyboard = false;
public static Boolean show_soft_keyboard_now_showing = false;
public static long last_pressed_menu_key = 0L;
@@ -354,25 +350,6 @@ public class Navit extends Activity {
Notification NavitNotification = builder.build();
nm.notify(R.string.app_name, NavitNotification);// Show the notification
- // Status and navigation bar sizes
- // These are platform defaults and do not change with rotation, but we have to figure out which ones apply
- // (is the navigation bar visible? on the side or at the bottom?)
- Resources resources = getResources();
- int shid = resources.getIdentifier("status_bar_height", "dimen", "android");
- int adhid = resources.getIdentifier("action_bar_default_height", "dimen", "android");
- int nhid = resources.getIdentifier("navigation_bar_height", "dimen", "android");
- int nhlid = resources.getIdentifier("navigation_bar_height_landscape", "dimen", "android");
- int nwid = resources.getIdentifier("navigation_bar_width", "dimen", "android");
- status_bar_height = (shid > 0) ? resources.getDimensionPixelSize(shid) : 0;
- action_bar_default_height = (adhid > 0) ? resources.getDimensionPixelSize(adhid) : 0;
- navigation_bar_height = (nhid > 0) ? resources.getDimensionPixelSize(nhid) : 0;
- navigation_bar_height_landscape = (nhlid > 0) ? resources.getDimensionPixelSize(nhlid) : 0;
- navigation_bar_width = (nwid > 0) ? resources.getDimensionPixelSize(nwid) : 0;
- Log.d(TAG, String.format(
- "status_bar_height=%d, action_bar_default_height=%d, navigation_bar_height=%d, "
- + "navigation_bar_height_landscape=%d, navigation_bar_width=%d",
- status_bar_height, action_bar_default_height, navigation_bar_height,
- navigation_bar_height_landscape, navigation_bar_width));
if ((ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
|| (ContextCompat.checkSelfPermission(this,
@@ -502,6 +479,7 @@ public class Navit extends Activity {
}
}
Log.d(TAG, "onResume");
+
if (show_soft_keyboard_now_showing) {
/* Calling showNativeKeyboard() directly won't work here, we need to use the message queue */
View cf = getCurrentFocus();
diff --git a/navit/android/src/org/navitproject/navit/NavitGraphics.java b/navit/android/src/org/navitproject/navit/NavitGraphics.java
index ba6b87bde..bb8ec8335 100644
--- a/navit/android/src/org/navitproject/navit/NavitGraphics.java
+++ b/navit/android/src/org/navitproject/navit/NavitGraphics.java
@@ -20,9 +20,11 @@
package org.navitproject.navit;
import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
@@ -64,9 +66,15 @@ public class NavitGraphics {
private int bgcolor;
private float trackball_x;
private float trackball_y;
+ private int padding_left = 0;
+ private int padding_right = 0;
+ private int padding_top = 0;
+ private int padding_bottom = 0;
private View view;
- private SystemBarTintView navigationTintView;
- private SystemBarTintView statusTintView;
+ private SystemBarTintView leftTintView;
+ private SystemBarTintView rightTintView;
+ private SystemBarTintView topTintView;
+ private SystemBarTintView bottomTintView;
private FrameLayout frameLayout;
private RelativeLayout relativelayout;
private NavitCamera camera;
@@ -80,11 +88,17 @@ public class NavitGraphics {
public void setBackgroundColor(int bgcolor) {
this.bgcolor = bgcolor;
- if (navigationTintView != null) {
- navigationTintView.setBackgroundColor(bgcolor);
+ if (leftTintView != null) {
+ leftTintView.setBackgroundColor(bgcolor);
}
- if (statusTintView != null) {
- statusTintView.setBackgroundColor(bgcolor);
+ if (rightTintView != null) {
+ rightTintView.setBackgroundColor(bgcolor);
+ }
+ if (topTintView != null) {
+ topTintView.setBackgroundColor(bgcolor);
+ }
+ if (bottomTintView != null) {
+ bottomTintView.setBackgroundColor(bgcolor);
}
}
@@ -574,10 +588,14 @@ public class NavitGraphics {
if (Build.VERSION.SDK_INT >= 19) {
frameLayout = new FrameLayout(activity);
frameLayout.addView(relativelayout);
- navigationTintView = new SystemBarTintView(activity);
- statusTintView = new SystemBarTintView(activity);
- frameLayout.addView(navigationTintView);
- frameLayout.addView(statusTintView);
+ leftTintView = new SystemBarTintView(activity);
+ rightTintView = new SystemBarTintView(activity);
+ topTintView = new SystemBarTintView(activity);
+ bottomTintView = new SystemBarTintView(activity);
+ frameLayout.addView(leftTintView);
+ frameLayout.addView(rightTintView);
+ frameLayout.addView(topTintView);
+ frameLayout.addView(bottomTintView);
activity.setContentView(frameLayout);
} else {
activity.setContentView(relativelayout);
@@ -688,82 +706,52 @@ public class NavitGraphics {
*
*/
private void adjustSystemBarsTintingViews() {
-
- /* frameLayout is only created on platforms supporting navigation and status bar tinting */
- if (frameLayout == null) {
- return;
- }
- if (activity == null) {
- Log.w(TAG, "Main Activity is not a Navit instance, cannot update padding");
- return;
- }
-
- Navit navit = activity;
-
- /*
- * Determine visibility of status bar.
- * The status bar is always visible unless we are in fullscreen mode.
- */
- final Boolean isStatusShowing = !navit.isFullscreen;
-
- /*
- * Determine visibility of navigation bar.
- * This logic is based on the presence of a hardware menu button and is known to work on
- * devices which allow switching between hw and sw buttons (OnePlus One running CyanogenMod).
- */
- final Boolean isNavShowing = !ViewConfigurationCompat.hasPermanentMenuKey(ViewConfiguration.get(navit));
- Log.d(TAG, String.format("isStatusShowing=%b isNavShowing=%b", isStatusShowing, isNavShowing));
-
- /*
- * Determine where the navigation bar would be displayed.
- * Logic is taken from AOSP RenderSessionImpl.findNavigationBar()
- * platform/frameworks/base/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
- */
- final Boolean isLandscape = (navit.getResources().getConfiguration().orientation
- == Configuration.ORIENTATION_LANDSCAPE);
- final Boolean isNavAtBottom = (!isLandscape)
- || (navit.getResources().getConfiguration().smallestScreenWidthDp >= 600);
- Log.d(TAG, String.format("isNavAtBottom=%b (Configuration.smallestScreenWidthDp=%d, isLandscape=%b)",
- isNavAtBottom, navit.getResources().getConfiguration().smallestScreenWidthDp, isLandscape));
-
- int left = 0;
- int top = isStatusShowing ? Navit.status_bar_height : 0;
- int right = (isNavShowing && !isNavAtBottom) ? Navit.navigation_bar_width : 0;
- final int bottom = (!(isNavShowing
- && isNavAtBottom)) ? 0 : (
- isLandscape ? Navit.navigation_bar_height_landscape : Navit.navigation_bar_height);
-
/* hide tint bars during update to prevent ugly effects */
- statusTintView.setVisibility(View.GONE);
- navigationTintView.setVisibility(View.GONE);
+ leftTintView.setVisibility(View.GONE);
+ rightTintView.setVisibility(View.GONE);
+ topTintView.setVisibility(View.GONE);
+ bottomTintView.setVisibility(View.GONE);
frameLayout.post(new Runnable() {
@Override
public void run() {
- statusTintView.setVisibility(isStatusShowing ? View.VISIBLE : View.GONE);
- FrameLayout.LayoutParams statusLayoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
- Navit.status_bar_height, Gravity.TOP);
-
- /* Prevent tint views from overlapping when navigation is on the right */
- statusLayoutParams.setMargins(0, 0,
- (isNavShowing && !isNavAtBottom) ? Navit.navigation_bar_width : 0, 0);
- statusTintView.setLayoutParams(statusLayoutParams);
- Log.d(TAG, String.format("statusTintView: width=%d height=%d",
- statusTintView.getWidth(), statusTintView.getHeight()));
- navigationTintView.setVisibility(isNavShowing ? View.VISIBLE : View.GONE);
- LayoutParams navigationLayoutParams = new FrameLayout.LayoutParams(
- isNavAtBottom ? LayoutParams.MATCH_PARENT : Navit.navigation_bar_width, // X
- isNavAtBottom ? bottom : LayoutParams.MATCH_PARENT, // Y
- Gravity.BOTTOM | Gravity.RIGHT);
- navigationTintView.setLayoutParams(navigationLayoutParams);
- Log.d(TAG, String.format("navigationTintView: width=%d height=%d",
- navigationTintView.getWidth(), navigationTintView.getHeight()));
+ FrameLayout.LayoutParams leftLayoutParams = new FrameLayout.LayoutParams(padding_left,
+ LayoutParams.MATCH_PARENT, Gravity.BOTTOM | Gravity.LEFT);
+ leftTintView.setLayoutParams(leftLayoutParams);
+ Log.d(TAG, String.format("leftTintView: width=%d height=%d",
+ leftTintView.getWidth(), leftTintView.getHeight()));
+
+ FrameLayout.LayoutParams rightLayoutParams = new FrameLayout.LayoutParams(padding_right,
+ LayoutParams.MATCH_PARENT, Gravity.BOTTOM | Gravity.RIGHT);
+ rightTintView.setLayoutParams(rightLayoutParams);
+ Log.d(TAG, String.format("rightTintView: width=%d height=%d",
+ rightTintView.getWidth(), rightTintView.getHeight()));
+
+ FrameLayout.LayoutParams topLayoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+ padding_top, Gravity.TOP);
+ /* Prevent horizontal and vertical tint views from overlapping */
+ topLayoutParams.setMargins(padding_left, 0, padding_right, 0);
+ topTintView.setLayoutParams(topLayoutParams);
+ Log.d(TAG, String.format("topTintView: width=%d height=%d",
+ topTintView.getWidth(), topTintView.getHeight()));
+
+ FrameLayout.LayoutParams bottomLayoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+ padding_bottom, Gravity.BOTTOM);
+ /* Prevent horizontal and vertical tint views from overlapping */
+ bottomLayoutParams.setMargins(padding_left, 0, padding_right, 0);
+ bottomTintView.setLayoutParams(bottomLayoutParams);
+ Log.d(TAG, String.format("bottomTintView: width=%d height=%d",
+ bottomTintView.getWidth(), bottomTintView.getHeight()));
+
+ /* show tint bars again */
+ leftTintView.setVisibility(View.VISIBLE);
+ rightTintView.setVisibility(View.VISIBLE);
+ topTintView.setVisibility(View.VISIBLE);
+ bottomTintView.setVisibility(View.VISIBLE);
}
});
- Log.d(TAG, String.format("Padding left=%d top=%d right=%d bottom=%d", left, top, right, bottom));
-
- PaddingChangedCallback(PaddingChangedCallbackID, left, top, right, bottom);
+ PaddingChangedCallback(PaddingChangedCallbackID, padding_left, padding_top, padding_right, padding_bottom);
}
/**
@@ -773,12 +761,103 @@ public class NavitGraphics {
* {@code onSizeChanged()} event handler fires or when toggling Fullscreen mode.
*
*/
+ @TargetApi(23)
public void handleResize(int w, int h) {
if (this.parent_graphics != null) {
this.parent_graphics.handleResize(w, h);
} else {
Log.d(TAG, String.format("handleResize w=%d h=%d", w, h));
+ /* Fallback if we can't determine padding: assume 0 all around */
+ padding_left = 0;
+ padding_right = 0;
+ padding_top = 0;
+ padding_bottom = 0;
+
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
+ /* On API 23+ we can query window insets to determine the area which is obscured by the system bars. */
+ if (view == null) {
+ Log.e(TAG, "view is null!");
+ } else {
+ Log.e(TAG, String.format("view w=%d h=%d x=%.0f y=%.0f",
+ view.getWidth(), view.getHeight(), view.getX(), view.getY()));
+ if (view.getRootWindowInsets() == null)
+ Log.e(TAG, "No root window insets");
+ else {
+ Log.e(TAG, String.format("RootWindowInsets left=%d right=%d top=%d bottom=%d",
+ view.getRootWindowInsets().getSystemWindowInsetLeft(),
+ view.getRootWindowInsets().getSystemWindowInsetRight(),
+ view.getRootWindowInsets().getSystemWindowInsetTop(),
+ view.getRootWindowInsets().getSystemWindowInsetBottom()));
+ padding_left = view.getRootWindowInsets().getSystemWindowInsetLeft();
+ padding_right = view.getRootWindowInsets().getSystemWindowInsetRight();
+ padding_top = view.getRootWindowInsets().getSystemWindowInsetTop();
+ padding_bottom = view.getRootWindowInsets().getSystemWindowInsetBottom();
+ }
+ }
+ } else {
+ /*
+ * Android 4.x does not support window insets at all, and Android 5.x does not support root window
+ * insets, forcing us to make an educated guess:
+ *
+ * Status and navigation bar sizes are platform defaults and do not change with rotation, but we have
+ * to figure out which ones apply.
+ *
+ * The status bar is always visible unless we are in fullscreen mode.
+ *
+ * The navigation bar is shown on devices that report they have no physical menu button. This seems to
+ * work even on devices that allow disabling the physical buttons (and use the navigation bar, in which
+ * case they report no physical menu button is available; tested with a OnePlus One running CyanogenMod).
+ *
+ * If shown, the navigation bar may appear on the side or at the bottom. The logic to determine this is
+ * taken from AOSP RenderSessionImpl.findNavigationBar()
+ * platform/frameworks/base/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+ */
+ Resources resources = view.getResources();
+ int shid = resources.getIdentifier("status_bar_height", "dimen", "android");
+ int adhid = resources.getIdentifier("action_bar_default_height", "dimen", "android");
+ int nhid = resources.getIdentifier("navigation_bar_height", "dimen", "android");
+ int nhlid = resources.getIdentifier("navigation_bar_height_landscape", "dimen", "android");
+ int nwid = resources.getIdentifier("navigation_bar_width", "dimen", "android");
+ int status_bar_height = (shid > 0) ? resources.getDimensionPixelSize(shid) : 0;
+ int action_bar_default_height = (adhid > 0) ? resources.getDimensionPixelSize(adhid) : 0;
+ int navigation_bar_height = (nhid > 0) ? resources.getDimensionPixelSize(nhid) : 0;
+ int navigation_bar_height_landscape = (nhlid > 0) ? resources.getDimensionPixelSize(nhlid) : 0;
+ int navigation_bar_width = (nwid > 0) ? resources.getDimensionPixelSize(nwid) : 0;
+ Log.d(TAG, String.format(
+ "status_bar_height=%d, action_bar_default_height=%d, navigation_bar_height=%d, "
+ + "navigation_bar_height_landscape=%d, navigation_bar_width=%d",
+ status_bar_height, action_bar_default_height, navigation_bar_height,
+ navigation_bar_height_landscape, navigation_bar_width));
+
+ if (activity == null) {
+ Log.w(TAG, "Main Activity is not a Navit instance, cannot update padding");
+ } else if (frameLayout != null) {
+ /* frameLayout is only created on platforms supporting navigation and status bar tinting */
+
+ Navit navit = activity;
+ boolean isStatusShowing = !navit.isFullscreen;
+ boolean isNavShowing = !ViewConfigurationCompat.hasPermanentMenuKey(ViewConfiguration.get(navit));
+ Log.d(TAG, String.format("isStatusShowing=%b isNavShowing=%b", isStatusShowing, isNavShowing));
+
+ boolean isLandscape = (navit.getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_LANDSCAPE);
+ boolean isNavAtBottom = (!isLandscape)
+ || (navit.getResources().getConfiguration().smallestScreenWidthDp >= 600);
+ Log.d(TAG, String.format("isNavAtBottom=%b (Configuration.smallestScreenWidthDp=%d, isLandscape=%b)",
+ isNavAtBottom, navit.getResources().getConfiguration().smallestScreenWidthDp, isLandscape));
+
+ padding_left = 0;
+ padding_top = isStatusShowing ? status_bar_height : 0;
+ padding_right = (isNavShowing && !isNavAtBottom) ? navigation_bar_width : 0;
+ padding_bottom = (!(isNavShowing && isNavAtBottom)) ? 0 : (
+ isLandscape ? navigation_bar_height_landscape : navigation_bar_height);
+ }
+ }
+
+ Log.d(TAG, String.format("Padding left=%d top=%d right=%d bottom=%d",
+ padding_left, padding_top, padding_right, padding_bottom));
+
adjustSystemBarsTintingViews();
draw_bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);