From 0e0a294a61156108ddd85b73da87794c51795a63 Mon Sep 17 00:00:00 2001 From: Alexey Kulish Date: Fri, 16 Oct 2015 12:27:07 +0300 Subject: [PATCH] Map marker should not be overlapped with context menu --- .../MapContextMenuFragment.java | 92 ++++++++++++++---- .../editors/PointEditorFragment.java | 94 ++++++++++++++++--- 2 files changed, 152 insertions(+), 34 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java index 72cda8ebe0..4fa23f35da 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java @@ -29,6 +29,7 @@ import android.widget.TextView; import net.osmand.PlatformUtil; import net.osmand.data.LatLon; +import net.osmand.data.QuadPoint; import net.osmand.data.RotatedTileBox; import net.osmand.plus.IconsCache; import net.osmand.plus.OsmandApplication; @@ -51,8 +52,9 @@ public class MapContextMenuFragment extends Fragment { public static final String TAG = "MapContextMenuFragment"; private static final Log LOG = PlatformUtil.getLog(MapContextMenuFragment.class); - private static final float FAB_PADDING_TOP = 10f; - private static final float MARKER_PADDING_DP = 20f; + public static final float FAB_PADDING_TOP = 10f; + public static final float MARKER_PADDING_DP = 20f; + public static final float MARKER_PADDING_X_DP = 50f; private View view; private View mainView; @@ -69,6 +71,13 @@ public class MapContextMenuFragment extends Fragment { private int fabPaddingTopPx; private int markerPaddingPx; + private int markerPaddingXPx; + + private OsmandMapTileView map; + private double origMapCenterLat; + private double origMapCenterLon; + private int origMarkerX; + private int origMarkerY; private class SingleTapConfirm implements OnGestureListener { @@ -118,12 +127,22 @@ public class MapContextMenuFragment extends Fragment { fabPaddingTopPx = dpToPx(FAB_PADDING_TOP); markerPaddingPx = dpToPx(MARKER_PADDING_DP); + markerPaddingXPx = dpToPx(MARKER_PADDING_X_DP); menu = getMapActivity().getContextMenu(); if (savedInstanceState != null) { menu.restoreMenuState(savedInstanceState); } + map = getMapActivity().getMapView(); + origMapCenterLat = map.getLatitude(); + origMapCenterLon = map.getLongitude(); + RotatedTileBox box = map.getCurrentRotatedTileBox(); + double markerLat = menu.getLatLon().getLatitude(); + double markerLon = menu.getLatLon().getLongitude(); + origMarkerX = (int)box.getPixXFromLatLon(markerLat, markerLon); + origMarkerY = (int)box.getPixYFromLatLon(markerLat, markerLon); + view = inflater.inflate(R.layout.map_context_menu_fragment, container, false); mainView = view.findViewById(R.id.context_menu_main); @@ -155,7 +174,7 @@ public class MapContextMenuFragment extends Fragment { public boolean onTouch(View v, MotionEvent event) { if (singleTapDetector.onTouchEvent(event)) { - showOnMap(menu.getLatLon()); + showOnMap(menu.getLatLon(), true, false); if (hasMoved) { applyPosY(getViewY(), false); @@ -182,7 +201,7 @@ public class MapContextMenuFragment extends Fragment { hasMoved = true; float y = event.getY(); float newY = getViewY() + (y - dy); - setViewY((int) newY); + setViewY((int) newY, false); menuFullHeight = view.getHeight() - (int) newY + 10; if (!oldAndroid()) { @@ -256,12 +275,15 @@ public class MapContextMenuFragment extends Fragment { } }) .start(); + fabView.animate().y(getFabY(posY)) .setDuration(200) .setInterpolator(new DecelerateInterpolator()) .start(); + + adjustMapPosition(posY, true); } else { - setViewY(posY); + setViewY(posY, false); updateMainViewLayout(posY); } } @@ -387,6 +409,7 @@ public class MapContextMenuFragment extends Fragment { @Override public void onDestroyView() { super.onDestroyView(); + map.setLatLon(origMapCenterLat, origMapCenterLon); getMapActivity().getMapLayers().getMapControlsLayer().setControlsClickable(true); } @@ -430,7 +453,7 @@ public class MapContextMenuFragment extends Fragment { }); } - private void showOnMap(LatLon latLon) { + private void showOnMap(LatLon latLon, boolean updateCoords, boolean ignoreCoef) { MapActivity ctx = getMapActivity(); AnimateDraggingMapThread thread = ctx.getMapView().getAnimatedDraggingThread(); int fZoom = ctx.getMapView().getZoom(); @@ -438,11 +461,22 @@ public class MapContextMenuFragment extends Fragment { double flon = latLon.getLongitude(); RotatedTileBox cp = ctx.getMapView().getCurrentRotatedTileBox().copy(); - cp.setCenterLocation(0.5f, ctx.getMapView().getMapPosition() == OsmandSettings.BOTTOM_CONSTANT ? 0.15f : 0.5f); + if (ignoreCoef) { + cp.setCenterLocation(0.5f, 0.5f); + } else { + cp.setCenterLocation(0.5f, ctx.getMapView().getMapPosition() == OsmandSettings.BOTTOM_CONSTANT ? 0.15f : 0.5f); + } cp.setLatLonCenter(flat, flon); flat = cp.getLatFromPixel(cp.getPixWidth() / 2, cp.getPixHeight() / 2); flon = cp.getLonFromPixel(cp.getPixWidth() / 2, cp.getPixHeight() / 2); + if (updateCoords) { + origMapCenterLat = flat; + origMapCenterLon = flon; + origMarkerX = cp.getCenterPixelX(); + origMarkerY = cp.getCenterPixelY(); + } + thread.startMoving(flat, flon, fZoom, true); } @@ -516,7 +550,7 @@ public class MapContextMenuFragment extends Fragment { } } - private void setViewY(int y) { + private void setViewY(int y, boolean animated) { if (!oldAndroid()) { mainView.setY(y); fabView.setY(getFabY(y)); @@ -524,24 +558,41 @@ public class MapContextMenuFragment extends Fragment { mainView.setPadding(0, y, 0, 0); fabView.setPadding(0, getFabY(y), 0, 0); } - //adjustMapPosition(y); + adjustMapPosition(y, animated); } - private void adjustMapPosition(int y) { - OsmandMapTileView map = getMapActivity().getMapView(); + private void adjustMapPosition(int y, boolean animated) { double markerLat = menu.getLatLon().getLatitude(); double markerLon = menu.getLatLon().getLongitude(); - int markerX = (int)map.getCurrentRotatedTileBox().getPixXFromLatLon(markerLat, markerLon); - int markerY = (int)map.getCurrentRotatedTileBox().getPixYFromLatLon(markerLat, markerLon); + RotatedTileBox box = map.getCurrentRotatedTileBox(); + LatLon latlon = new LatLon(origMapCenterLat, origMapCenterLon); if (menu.isLandscapeLayout()) { - int menuX = dpToPx(menu.getLandscapeWidthDp()); - } else { - int menuY = y; - if (markerY + markerPaddingPx > menuY) { - int dy = markerY - (menuY - markerPaddingPx); - map.moveTo(0, dy); + int markerX = (int)box.getPixXFromLatLon(markerLat, markerLon); + int x = dpToPx(menu.getLandscapeWidthDp()); + if (markerX - markerPaddingXPx < x || markerX > origMarkerX) { + int dx = (x + markerPaddingXPx) - markerX; + if (markerX - dx <= origMarkerX) { + QuadPoint cp = box.getCenterPixelPoint(); + latlon = box.getLatLonFromPixel(cp.x - dx, cp.y); + } else { + latlon = box.getCenterLatLon(); + } } + } else { + int markerY = (int)box.getPixYFromLatLon(markerLat, markerLon); + if (markerY + markerPaddingPx > y || markerY < origMarkerY) { + int dy = markerY - (y - markerPaddingPx); + if (markerY - dy <= origMarkerY) { + QuadPoint cp = box.getCenterPixelPoint(); + latlon = box.getLatLonFromPixel(cp.x + 0, cp.y + dy); + } + } + } + if (animated) { + showOnMap(latlon, false, true); + } else { + map.setLatLon(latlon.getLatitude(), latlon.getLongitude()); } } @@ -559,7 +610,7 @@ public class MapContextMenuFragment extends Fragment { private void doLayoutMenu() { final int posY = getPosY(); - setViewY(posY); + setViewY(posY, true); updateMainViewLayout(posY); } @@ -577,6 +628,7 @@ public class MapContextMenuFragment extends Fragment { public void setFragmentVisibility(boolean visible) { if (visible) { view.setVisibility(View.VISIBLE); + adjustMapPosition(getPosY(), true); } else { view.setVisibility(View.GONE); } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragment.java index c3e779d8ef..ffb60c1d28 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragment.java @@ -11,13 +11,12 @@ import android.os.IBinder; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; import android.support.v7.widget.Toolbar; -import android.util.DisplayMetrics; -import android.util.Log; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; @@ -25,12 +24,18 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; +import net.osmand.data.LatLon; +import net.osmand.data.QuadPoint; +import net.osmand.data.RotatedTileBox; import net.osmand.plus.IconsCache; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.mapcontextmenu.MapContextMenu; import net.osmand.plus.mapcontextmenu.MapContextMenuFragment; import net.osmand.plus.mapcontextmenu.editors.dialogs.SelectCategoryDialogFragment; +import net.osmand.plus.views.AnimateDraggingMapThread; +import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.widgets.AutoCompleteTextViewEx; import net.osmand.util.Algorithms; @@ -38,6 +43,9 @@ import static android.util.TypedValue.COMPLEX_UNIT_DIP; public abstract class PointEditorFragment extends Fragment { + private View view; + private int mainViewHeight; + @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); @@ -58,7 +66,6 @@ public abstract class PointEditorFragment extends Fragment { getActivity().findViewById(R.id.MapHudButtonsOverlay).setVisibility(View.INVISIBLE); - View view; if (getEditor().isLandscapeLayout()) { view = inflater.inflate(R.layout.point_editor_fragment_land, container, false); } else { @@ -135,6 +142,8 @@ public abstract class PointEditorFragment extends Fragment { ImageView descriptionImage = (ImageView) view.findViewById(R.id.description_image); descriptionImage.setImageDrawable(getRowIcon(R.drawable.ic_action_note_dark)); + runLayoutListener(); + return view; } @@ -168,6 +177,69 @@ public abstract class PointEditorFragment extends Fragment { getActivity().findViewById(R.id.MapHudButtonsOverlay).setVisibility(View.VISIBLE); } + private void adjustMapPosition(boolean animated) { + OsmandMapTileView map = getMapActivity().getMapView(); + MapContextMenu menu = getMapActivity().getContextMenu(); + double markerLat = menu.getLatLon().getLatitude(); + double markerLon = menu.getLatLon().getLongitude(); + + RotatedTileBox box = map.getCurrentRotatedTileBox(); + int origMarkerY = (int)box.getPixYFromLatLon(markerLat, markerLon); + + int markerPaddingPx = dpToPx(MapContextMenuFragment.MARKER_PADDING_DP); + + int y = view.getHeight() - mainViewHeight; + + if (!menu.isLandscapeLayout()) { + int markerY = (int)box.getPixYFromLatLon(markerLat, markerLon); + if (markerY + markerPaddingPx > y || markerY < origMarkerY) { + int dy = markerY - (y - markerPaddingPx); + if (markerY - dy <= origMarkerY) { + QuadPoint cp = box.getCenterPixelPoint(); + LatLon latlon = box.getLatLonFromPixel(cp.x + 0, cp.y + dy); + double destLat = latlon.getLatitude(); + double destLon = latlon.getLongitude(); + if (animated) { + AnimateDraggingMapThread thread = map.getAnimatedDraggingThread(); + int fZoom = map.getZoom(); + double flat = destLat; + double flon = destLon; + + RotatedTileBox cbox = map.getCurrentRotatedTileBox().copy(); + cbox.setCenterLocation(0.5f, 0.5f); + cbox.setLatLonCenter(flat, flon); + flat = cbox.getLatFromPixel(cbox.getPixWidth() / 2, cbox.getPixHeight() / 2); + flon = cbox.getLonFromPixel(cbox.getPixWidth() / 2, cbox.getPixHeight() / 2); + + thread.startMoving(flat, flon, fZoom, true); + } else { + map.setLatLon(destLat, destLon); + } + } + } + } + } + + private void runLayoutListener() { + ViewTreeObserver vto = view.getViewTreeObserver(); + vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + + @Override + public void onGlobalLayout() { + mainViewHeight = view.findViewById(R.id.main_view).getHeight(); + + ViewTreeObserver obs = view.getViewTreeObserver(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + obs.removeOnGlobalLayoutListener(this); + } else { + obs.removeGlobalOnLayoutListener(this); + } + adjustMapPosition(true); + } + + }); + } + private void hideKeyboard() { InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE); View currentFocus = getActivity().getCurrentFocus(); @@ -203,10 +275,10 @@ public abstract class PointEditorFragment extends Fragment { public abstract String getToolbarTitle(); public void setCategory(String name) { - AutoCompleteTextViewEx categoryEdit = (AutoCompleteTextViewEx) getView().findViewById(R.id.category_edit); + AutoCompleteTextViewEx categoryEdit = (AutoCompleteTextViewEx) view.findViewById(R.id.category_edit); String n = name.length() == 0 ? getString(R.string.shared_string_favorites) : name; categoryEdit.setText(n); - ImageView categoryImage = (ImageView) getView().findViewById(R.id.category_image); + ImageView categoryImage = (ImageView) view.findViewById(R.id.category_image); categoryImage.setImageDrawable(getCategoryIcon()); } @@ -252,29 +324,23 @@ public abstract class PointEditorFragment extends Fragment { public abstract Drawable getCategoryIcon(); public String getNameTextValue() { - EditText nameEdit = (EditText) getView().findViewById(R.id.name_edit); + EditText nameEdit = (EditText) view.findViewById(R.id.name_edit); return nameEdit.getText().toString().trim(); } public String getCategoryTextValue() { - AutoCompleteTextViewEx categoryEdit = (AutoCompleteTextViewEx) getView().findViewById(R.id.category_edit); + AutoCompleteTextViewEx categoryEdit = (AutoCompleteTextViewEx) view.findViewById(R.id.category_edit); String name = categoryEdit.getText().toString().trim(); return name.equals(getString(R.string.shared_string_favorites)) ? "" : name; } public String getDescriptionTextValue() { - EditText descriptionEdit = (EditText) getView().findViewById(R.id.description_edit); + EditText descriptionEdit = (EditText) view.findViewById(R.id.description_edit); String res = descriptionEdit.getText().toString().trim(); return Algorithms.isEmpty(res) ? null : res; } // Utils - private int getScreenHeight() { - DisplayMetrics dm = new DisplayMetrics(); - getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); - return dm.heightPixels; - } - private int dpToPx(float dp) { Resources r = getActivity().getResources(); return (int) TypedValue.applyDimension(