diff options
Diffstat (limited to 'navit/android/src/org/navitproject/navit/NavitGraphics.java')
-rw-r--r-- | navit/android/src/org/navitproject/navit/NavitGraphics.java | 189 |
1 files changed, 181 insertions, 8 deletions
diff --git a/navit/android/src/org/navitproject/navit/NavitGraphics.java b/navit/android/src/org/navitproject/navit/NavitGraphics.java index 728b49878..a41ab52be 100644 --- a/navit/android/src/org/navitproject/navit/NavitGraphics.java +++ b/navit/android/src/org/navitproject/navit/NavitGraphics.java @@ -25,23 +25,31 @@ import java.util.ArrayList; 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.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PointF; import android.graphics.Rect; +import android.os.Build; import android.os.Handler; import android.os.Message; import android.util.FloatMath; import android.util.Log; import android.view.ContextMenu; +import android.view.Gravity; import android.view.KeyEvent; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup.LayoutParams; import android.view.inputmethod.InputMethodManager; +import android.widget.FrameLayout; import android.widget.RelativeLayout; @@ -55,8 +63,12 @@ public class NavitGraphics int pos_y; int pos_wraparound; int overlay_disabled; + int bgcolor; float trackball_x, trackball_y; View view; + SystemBarTintView navigationTintView; + SystemBarTintView statusTintView; + FrameLayout frameLayout; RelativeLayout relativelayout; NavitCamera camera; Activity activity; @@ -68,6 +80,14 @@ public class NavitGraphics private static long interval_for_long_press = 200L; private Handler timer_handler = new Handler(); + + public void setBackgroundColor(int bgcolor) { + this.bgcolor = bgcolor; + if (navigationTintView != null) + navigationTintView.setBackgroundColor(bgcolor); + if (statusTintView != null) + statusTintView.setBackgroundColor(bgcolor); + } public void SetCamera(int use_camera) { @@ -197,11 +217,8 @@ public class NavitGraphics Log.e("Navit", "NavitGraphics -> onSizeChanged scaledDensity=" + Navit.metrics.scaledDensity); super.onSizeChanged(w, h, oldw, oldh); - draw_bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - draw_canvas = new Canvas(draw_bitmap); - bitmap_w = w; - bitmap_h = h; - SizeChangedCallback(SizeChangedCallbackID, w, h); + + handleResize(w, h); } public void do_longpress_action() @@ -352,7 +369,7 @@ public class NavitGraphics { float x = a.x - b.x; float y = a.y - b.y; - return FloatMath.sqrt(x * x + y * y); + return (float)Math.sqrt(x * x + y * y); } private PointF getFloatValue(Object instance, Object argument) @@ -685,6 +702,15 @@ public class NavitGraphics } + private class SystemBarTintView extends View { + + public SystemBarTintView(Context context) { + super(context); + this.setBackgroundColor(bgcolor); + } + + } + public NavitGraphics(final Activity activity, NavitGraphics parent, int x, int y, int w, int h, int wraparound, int use_camera) { @@ -704,7 +730,22 @@ public class NavitGraphics } relativelayout.addView(view); + /* The navigational and status bar tinting code is meaningful only on API19+ */ + 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); + activity.setContentView(frameLayout); + } + else + { activity.setContentView(relativelayout); + } + view.requestFocus(); } else @@ -781,6 +822,7 @@ public class NavitGraphics }; public native void SizeChangedCallback(int id, int x, int y); + public native void PaddingChangedCallback(int id, int left, int right, int top, int bottom); public native void KeypressCallback(int id, String s); public native int CallbackMessageChannel(int i, String s); public native void ButtonCallback(int id, int pressed, int button, int x, int y); @@ -789,13 +831,144 @@ public class NavitGraphics public static native String[][] GetAllCountries(); private Canvas draw_canvas; private Bitmap draw_bitmap; - private int SizeChangedCallbackID, ButtonCallbackID, MotionCallbackID, KeypressCallbackID; + private int SizeChangedCallbackID, PaddingChangedCallbackID, ButtonCallbackID, MotionCallbackID, KeypressCallbackID; // private int count; + + /** + * @brief Adjust views used to tint navigation and status bars. + * + * This method is called from handleResize. + * + * It (re-)evaluates if and where the navigation bar is going to be shown, and calculates the + * padding for objects which should not be obstructed. + * + */ + private void adjustSystemBarsTintingViews() { + + /* frameLayout is only created on platforms supporting navigation and status bar tinting */ + if (frameLayout == null) + return; + + if (!(activity instanceof Navit)) { + Log.e("NavitGraphics", "Main Activity is not a Navit instance, cannot update padding"); + return; + } + + Navit 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 = !ViewConfiguration.get(navit.getApplication()).hasPermanentMenuKey(); + Log.d("NavitGraphics", 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("NavitGraphics", 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); + 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("NavitGraphics", 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("NavitGraphics", String.format("navigationTintView: width=%d height=%d", + navigationTintView.getWidth(), navigationTintView.getHeight())); + } + }); + + Log.d("NavitGraphics", String.format("Padding left=%d top=%d right=%d bottom=%d", left, top, right, bottom)); + + PaddingChangedCallback(PaddingChangedCallbackID, left, top, right, bottom); + } + + /** + * @brief Handles resize events. + * + * This method is called whenever the main View is resized in any way. This is the case when its + * {@code onSizeChanged()} event handler fires or when toggling Fullscreen mode. + * + */ + public void handleResize(int w, int h) { + if (this.parent_graphics != null) + this.parent_graphics.handleResize(w, h); + else { + Log.d("NavitGraphics", String.format("handleResize w=%d h=%d", w, h)); + + adjustSystemBarsTintingViews(); + + draw_bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + draw_canvas = new Canvas(draw_bitmap); + bitmap_w = w; + bitmap_h = h; + SizeChangedCallback(SizeChangedCallbackID, w, h); + } + } + + /** + * @brief Returns whether the device has a hardware menu button. + * + * Only Android versions starting with ICS (API version 14) support the API call to detect the presence of a + * Menu button. On earlier Android versions, the following assumptions will be made: On API levels up to 10, + * this method will always return {@code true}, as these Android versions relied on devices having a physical + * Menu button. On API levels 11 through 13 (Honeycomb releases), this method will always return + * {@code false}, as Honeycomb was a tablet-only release and did not require devices to have a Menu button. + * + * Note that this method is not aware of non-standard mechanisms on some customized builds of Android. For + * example, CyanogenMod has an option to add a menu button to the navigation bar. Even with that option, + * this method will still return `false`. + */ + public boolean hasMenuButton() { + if (Build.VERSION.SDK_INT <= 10) + return true; + else if (Build.VERSION.SDK_INT <= 13) + return false; + else + return ViewConfiguration.get(activity.getApplication()).hasPermanentMenuKey(); + } + public void setSizeChangedCallback(int id) { SizeChangedCallbackID = id; } + public void setPaddingChangedCallback(int id) + { + PaddingChangedCallbackID = id; + } public void setButtonCallback(int id) { ButtonCallbackID = id; @@ -921,7 +1094,7 @@ public class NavitGraphics //Log.e("NavitGraphics","draw_image"); // float fx = x; // float fy = y; - draw_canvas.drawBitmap(bitmap, x, y, paint); + draw_canvas.drawBitmap(bitmap, x, y, null); } /* takes an image and draws it on the screen as a prerendered maptile |