Update map controls to display zoom in/out conditionally

This commit is contained in:
vshcherb 2014-03-11 09:45:40 +01:00
parent 6ff788dba6
commit 2355433947
7 changed files with 569 additions and 371 deletions

View file

@ -28,7 +28,7 @@ public class MapTileDownloader {
public static int TILE_DOWNLOAD_SECONDS_TO_WORK = 25;
public static final long TIMEOUT_AFTER_EXCEEDING_LIMIT_ERRORS = 15000;
public static final int TILE_DOWNLOAD_MAX_ERRORS_PER_TIMEOUT = 50;
private static final int CONNECTION_TIMEOUT = 10000;
private static final int CONNECTION_TIMEOUT = 30000;
private static MapTileDownloader downloader = null;

View file

@ -23,7 +23,6 @@ import net.osmand.plus.OsmAndConstants;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.OsmandSettings.AutoZoomMap;
import net.osmand.plus.PoiFilter;
import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper;

View file

@ -1,76 +1,39 @@
package net.osmand.plus.views;
import gnu.trove.list.array.TIntArrayList;
import java.util.ArrayList;
import java.util.List;
import net.londatiga.android.ActionItem;
import net.londatiga.android.QuickAction;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmAndConstants;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.OsmandSettings.CommonPreference;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import net.osmand.plus.views.controls.MapMenuControls;
import net.osmand.plus.views.controls.MapZoomControls;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.text.TextPaint;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
public class MapControlsLayer extends OsmandMapLayer {
private static final int SHOW_ZOOM_LEVEL_MSG_ID = OsmAndConstants.UI_HANDLER_MAP_CONTROLS + 1;
private static final int SHOW_ZOOM_BUTTON_MSG_ID = OsmAndConstants.UI_HANDLER_MAP_CONTROLS + 2;
private static final int SHOW_ZOOM_LEVEL_DELAY = 1000;
private static final int SHOW_ZOOM_LEVEL_BUTTON_DELAY = 1500;
private static final int HOVER_COLOR = 0xffC8C8C8;
private OsmandMapTileView view;
private final MapActivity activity;
private Handler showUIHandler;
private final MapActivity mapActivity;
private boolean showZoomLevel = false;
private boolean showZoomLevelButton = false;
private int shadowColor = Color.WHITE;
private MapZoomControls zoomControls;
private MapMenuControls mapMenuControls;
private Button zoomInButton;
private Button zoomOutButton;
private TextPaint zoomTextPaint;
private Drawable zoomShadow;
private Bitmap mapMagnifier;
private Paint bitmapPaint;
private Button backToMenuButton;
private Drawable modeShadow;
private Drawable rulerDrawable;
private TextPaint rulerTextPaint;
private final static double screenRulerPercent = 0.25;
private float scaleCoefficient;
@ -78,9 +41,13 @@ public class MapControlsLayer extends OsmandMapLayer {
private LinearLayout transparencyBarLayout;
private static CommonPreference<Integer> settingsToTransparency;
private Drawable rulerDrawable;
private TextPaint rulerTextPaint;
private final static double screenRulerPercent = 0.25;
public MapControlsLayer(MapActivity activity){
this.activity = activity;
this.mapActivity = activity;
}
@ -91,17 +58,15 @@ public class MapControlsLayer extends OsmandMapLayer {
@Override
public void initLayer(final OsmandMapTileView view) {
this.view = view;
scaleCoefficient = view.getScaleCoefficient();
FrameLayout parent = (FrameLayout) view.getParent();
showUIHandler = new Handler();
initZoomButtons(view, parent);
initBackToMenuButton(view, parent);
Handler showUIHandler = new Handler();
zoomControls = new MapZoomControls(mapActivity, showUIHandler, scaleCoefficient);
zoomControls.init(parent);
mapMenuControls = new MapMenuControls(mapActivity, showUIHandler, scaleCoefficient);
mapMenuControls.init(parent);
mapMenuControls.show(parent);
initRuler(view, parent);
initTransparencyBar(view, parent);
}
@ -112,336 +77,44 @@ public class MapControlsLayer extends OsmandMapLayer {
@Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings nightMode) {
BaseMapLayer mainLayer = view.getMainLayer();
boolean zoomInEnabled = mainLayer != null && tileBox.getZoom() < mainLayer.getMaximumShownMapZoom();
boolean zoomOutEnabled = mainLayer != null && tileBox.getZoom() > mainLayer.getMinimumShownMapZoom();
if(zoomInButton.isEnabled() != zoomInEnabled){
zoomInButton.setEnabled(zoomInEnabled);
}
if(zoomOutButton.isEnabled() != zoomOutEnabled){
zoomOutButton.setEnabled(zoomOutEnabled);
}
drawApplicationMode(canvas, nightMode != null && nightMode.isNightMode());
if(view.isZooming()){
showZoomLevel = true;
showZoomLevelButton = false;
showUIHandler.removeMessages(SHOW_ZOOM_LEVEL_MSG_ID);
showUIHandler.removeMessages(SHOW_ZOOM_BUTTON_MSG_ID);
} else {
if(showZoomLevel && view.getSettings().SHOW_RULER.get()){
hideZoomLevelInTime();
}
}
int sh = Color.WHITE;
if (nightMode != null && nightMode.isNightMode()) {
sh = Color.TRANSPARENT;
}
if(shadowColor != sh) {
shadowColor = sh;
zoomTextPaint.setColor(sh == Color.WHITE ? Color.BLACK : 0xffC8C8C8);
rulerTextPaint.setColor(sh == Color.WHITE ? Color.BLACK : 0xffC8C8C8);
int textColor = sh == Color.WHITE ? Color.BLACK : HOVER_COLOR;
rulerTextPaint.setColor(textColor);
zoomControls.setShadowColor(textColor, sh);
mapMenuControls.setShadowColor(textColor, sh);
}
boolean drawZoomLevel = showZoomLevel || !view.getSettings().SHOW_RULER.get();
if (drawZoomLevel) {
drawZoomLevel(canvas, tileBox, !showZoomLevelButton);
} else {
drawRuler(canvas, tileBox);
boolean showZooms = !mapActivity.getRoutingHelper().isRouteCalculated();
if(showZooms != zoomControls.isVisible()){
if(showZooms) {
zoomControls.show((FrameLayout) mapActivity.getMapView().getParent());
} else {
zoomControls.hide((FrameLayout) mapActivity.getMapView().getParent());
}
}
}
private ApplicationMode cacheApplicationMode = null;
private Drawable cacheAppModeIcon = null;
private void drawApplicationMode(Canvas canvas, boolean nightMode) {
ApplicationMode appMode = view.getSettings().getApplicationMode();
if(appMode != cacheApplicationMode){
modeShadow.setBounds(backToMenuButton.getLeft() + (int) (2 * scaleCoefficient), backToMenuButton.getTop() - (int) (24 * scaleCoefficient),
backToMenuButton.getRight() - (int) (4 * scaleCoefficient), backToMenuButton.getBottom());
cacheAppModeIcon = view.getResources().getDrawable(appMode.getSmallIcon(nightMode));
int l = modeShadow.getBounds().left + (modeShadow.getBounds().width() - cacheAppModeIcon.getMinimumWidth()) / 2;
int t = (int) (modeShadow.getBounds().top + 2 * scaleCoefficient);
cacheAppModeIcon.setBounds(l, t, l + cacheAppModeIcon.getMinimumWidth(), t + cacheAppModeIcon.getMinimumHeight());
}
modeShadow.draw(canvas);
if(cacheAppModeIcon != null){
cacheAppModeIcon.draw(canvas);
if(showZooms) {
zoomControls.onDraw(canvas, tileBox, nightMode);
}
mapMenuControls.onDraw(canvas, tileBox, nightMode);
drawRuler(canvas, tileBox, nightMode);
}
private void onApplicationModePress() {
final QuickAction mQuickAction = new QuickAction(backToMenuButton);
List<ApplicationMode> vls = ApplicationMode.values(activity.getMyApplication().getSettings());
final ApplicationMode[] modes = vls.toArray(new ApplicationMode[vls.size()]);
int[] icons = new int[vls.size()];
int[] values = new int[vls.size()];
for(int k = 0; k < modes.length; k++) {
icons[k] = modes[k].getSmallIcon(false);
values[k] = modes[k].getStringResource();
}
for (int i = 0; i < modes.length; i++) {
final ActionItem action = new ActionItem();
action.setTitle(view.getResources().getString(values[i]));
action.setIcon(view.getResources().getDrawable(icons[i]));
final int j = i;
action.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
view.getSettings().APPLICATION_MODE.set(modes[j]);
mQuickAction.dismiss();
}
});
mQuickAction.addActionItem(action);
}
mQuickAction.setAnimStyle(QuickAction.ANIM_AUTO);
mQuickAction.show();
}
private void drawZoomLevel(Canvas canvas, RotatedTileBox tb, boolean drawZoomLevel) {
if (zoomShadow.getBounds().width() == 0) {
zoomShadow.setBounds(zoomInButton.getLeft() - 2, zoomInButton.getTop() - (int) (18 * scaleCoefficient),
zoomInButton.getRight(), zoomInButton.getBottom());
}
zoomShadow.draw(canvas);
if (drawZoomLevel) {
String zoomText = tb.getZoom() + "";
float frac = tb.getZoomScale();
if (frac != 0) {
int ifrac = (int) (frac * 10);
boolean pos = ifrac > 0;
zoomText += (pos ? "+" : "-");
zoomText += Math.abs(ifrac) / 10;
if (ifrac % 10 != 0) {
zoomText += "." + Math.abs(ifrac) % 10;
}
}
float length = zoomTextPaint.measureText(zoomText);
ShadowText.draw(zoomText, canvas, zoomInButton.getLeft() + (zoomInButton.getWidth() - length - 2) / 2,
zoomInButton.getTop() + 4 * scaleCoefficient, zoomTextPaint, shadowColor);
} else {
int size = (int) (16 * scaleCoefficient);
int top = (int) (zoomInButton.getTop() - size - 4 * scaleCoefficient);
int left = (int) (zoomInButton.getLeft() + (zoomInButton.getWidth() - mapMagnifier.getWidth() - 2 * scaleCoefficient) / 2);
// canvas density /2 ? size * 2
canvas.drawBitmap(mapMagnifier, null, new Rect(left, top, left + size * 2, top + size * 2), bitmapPaint);
}
}
private void hideZoomLevelInTime(){
if (!showUIHandler.hasMessages(SHOW_ZOOM_LEVEL_MSG_ID) &&
!showUIHandler.hasMessages(SHOW_ZOOM_BUTTON_MSG_ID)) {
sendMessageToShowZoomLevel();
}
}
private void sendMessageToShowZoomLevel() {
Message msg = Message.obtain(showUIHandler, new Runnable() {
@Override
public void run() {
showZoomLevelButton = true;
sendMessageToShowZoomButton();
view.refreshMap();
}
});
msg.what = SHOW_ZOOM_LEVEL_MSG_ID;
showUIHandler.sendMessageDelayed(msg, SHOW_ZOOM_LEVEL_DELAY);
}
private void sendMessageToShowZoomButton() {
Message msg = Message.obtain(showUIHandler, new Runnable() {
@Override
public void run() {
showZoomLevelButton = false;
showZoomLevel = false;
view.refreshMap();
}
});
msg.what = SHOW_ZOOM_BUTTON_MSG_ID;
showUIHandler.sendMessageDelayed(msg, SHOW_ZOOM_LEVEL_BUTTON_DELAY);
}
@Override
public boolean onSingleTap(PointF point, RotatedTileBox tileBox) {
if (modeShadow.getBounds().contains((int) point.x, (int) point.y)) {
onApplicationModePress();
if(mapMenuControls.onSingleTap(point, tileBox)) {
return true;
}
if (showZoomLevel && zoomShadow.getBounds().contains((int) point.x, (int) point.y)) {
getOnClickMagnifierListener(view).onLongClick(null);
if(zoomControls.isVisible() && zoomControls.onSingleTap(point, tileBox)) {
return true;
}
return false;
}
private void initBackToMenuButton(final OsmandMapTileView view, FrameLayout parent) {
android.widget.FrameLayout.LayoutParams params;
Context ctx = view.getContext();
backToMenuButton = new Button(ctx);
backToMenuButton.setContentDescription(ctx.getString(R.string.backToMenu));
backToMenuButton.setBackgroundResource(R.drawable.map_btn_menu);
params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM | Gravity.LEFT);
parent.addView(backToMenuButton, params);
backToMenuButton.setEnabled(true);
modeShadow = view.getResources().getDrawable(R.drawable.zoom_background);
backToMenuButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// double lat = activity.getMapView().getLatitude();
// double lon = activity.getMapView().getLongitude();
// MainMenuActivity.backToMainMenuDialog(activity, new LatLon(lat, lon));
activity.getMapActions().openOptionsMenuAsList();
}
});
activity.accessibleContent.add(backToMenuButton);
}
private void initRuler(OsmandMapTileView view, FrameLayout parent) {
rulerTextPaint = new TextPaint();
rulerTextPaint.setTextSize(20 * scaleCoefficient);
rulerTextPaint.setAntiAlias(true);
rulerDrawable = view.getResources().getDrawable(R.drawable.ruler);
}
private void initZoomButtons(final OsmandMapTileView view, FrameLayout parent) {
int minimumWidth = view.getResources().getDrawable(R.drawable.map_zoom_in).getMinimumWidth();
Context ctx = view.getContext();
ImageView bottomShadow = new ImageView(ctx);
bottomShadow.setBackgroundResource(R.drawable.bottom_shadow);
android.widget.FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM);
params.setMargins(0, 0, 0, 0);
parent.addView(bottomShadow, params);
zoomTextPaint = new TextPaint();
zoomTextPaint.setTextSize(18 * scaleCoefficient);
zoomTextPaint.setAntiAlias(true);
zoomTextPaint.setFakeBoldText(true);
zoomShadow = view.getResources().getDrawable(R.drawable.zoom_background).mutate();
mapMagnifier = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_magnifier);
bitmapPaint = new Paint();
zoomInButton = new Button(ctx);
zoomInButton.setBackgroundResource(R.drawable.map_zoom_in);
params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM | Gravity.RIGHT);
params.setMargins(0, 0, 0, 0);
zoomInButton.setContentDescription(ctx.getString(R.string.zoomIn));
parent.addView(zoomInButton, params);
zoomOutButton = new Button(ctx);
zoomOutButton.setBackgroundResource(R.drawable.map_zoom_out);
params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM | Gravity.RIGHT);
params.setMargins(0, 0, minimumWidth , 0);
zoomOutButton.setContentDescription(ctx.getString(R.string.zoomOut));
parent.addView(zoomOutButton, params);
activity.accessibleContent.add(zoomInButton);
activity.accessibleContent.add(zoomOutButton);
zoomInButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (view.isZooming()) {
activity.changeZoom(2);
} else {
activity.changeZoom(1);
}
}
});
final View.OnLongClickListener listener = getOnClickMagnifierListener(view);
zoomInButton.setOnLongClickListener(listener);
zoomOutButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
activity.changeZoom(- 1);
}
});
zoomOutButton.setOnLongClickListener(listener);
}
private static View.OnLongClickListener getOnClickMagnifierListener(final OsmandMapTileView view) {
final View.OnLongClickListener listener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View notUseCouldBeNull) {
final OsmandSettings.OsmandPreference<Float> zoomScale = view.getSettings().MAP_ZOOM_SCALE_BY_DENSITY;
final AlertDialog.Builder bld = new AlertDialog.Builder(view.getContext());
float scale = view.getZoomScale();
int p = (int) ((scale > 0 ? 1 : -1) * Math.round(scale * scale * 100)) + 100;
final TIntArrayList tlist = new TIntArrayList(new int[] { 75, 100, 150, 200, 300, 400, 500 });
final List<String> values = new ArrayList<String>();
int i = -1;
for (int k = 0; k <= tlist.size(); k++) {
final boolean end = k == tlist.size();
if (i == -1) {
if ((end || p < tlist.get(k))) {
values.add(p + "%");
i = k;
} else if (p == tlist.get(k)) {
i = k;
}
}
if (k < tlist.size()) {
values.add(tlist.get(k) + "%");
}
}
if (values.size() != tlist.size()) {
tlist.insert(i, p);
}
bld.setTitle(R.string.map_magnifier);
bld.setSingleChoiceItems(values.toArray(new String[values.size()]), i,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int p = tlist.get(which);
float newScale;
if (p >= 100) {
newScale = (float) Math.sqrt((tlist.get(which) - 100f) / 100f);
} else {
newScale = -(float) Math.sqrt((100f - tlist.get(which)) / 100f);
}
zoomScale.set(newScale - (float) Math.sqrt(Math.max(view.getDensity() - 1, 0)));
view.getAnimatedDraggingThread().startZooming(view.getZoom(),
view.getSettingsZoomScale(), false);
dialog.dismiss();
}
});
bld.show();
return true;
}
};
return listener;
}
///////////////// Transparency bar /////////////////////////
private void initTransparencyBar(final OsmandMapTileView view, FrameLayout parent) {
@ -472,7 +145,7 @@ public class MapControlsLayer extends OsmandMapLayer {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (settingsToTransparency != null) {
settingsToTransparency.set(progress);
MapControlsLayer.this.view.refreshMap();
mapActivity.getMapView().refreshMap();
}
}
});
@ -516,7 +189,19 @@ public class MapControlsLayer extends OsmandMapLayer {
double cacheRulerTileY = 0;
float cacheRulerTextLen = 0;
private void drawRuler(Canvas canvas, RotatedTileBox tb) {
private void initRuler(OsmandMapTileView view, FrameLayout parent) {
rulerTextPaint = new TextPaint();
rulerTextPaint.setTextSize(20 * scaleCoefficient);
rulerTextPaint.setAntiAlias(true);
rulerDrawable = view.getResources().getDrawable(R.drawable.ruler);
}
private void drawRuler(Canvas canvas, RotatedTileBox tb, DrawSettings nightMode) {
if( (zoomControls.isVisible() && zoomControls.isShowZoomLevel()) || !mapActivity.getMyApplication().getSettings().SHOW_RULER.get()){
return;
}
OsmandMapTileView view = mapActivity.getMapView();
// update cache
if (view.isZooming()) {
cacheRulerText = null;
@ -532,12 +217,11 @@ public class MapControlsLayer extends OsmandMapLayer {
int cacheRulerDistPix = (int) (pixDensity * roundedDist);
cacheRulerText = ShadowText.create(OsmAndFormatter.getFormattedDistance((float) roundedDist, view.getApplication()));
cacheRulerTextLen = zoomTextPaint.measureText(cacheRulerText.getText());
cacheRulerTextLen = rulerTextPaint.measureText(cacheRulerText.getText());
Rect bounds = rulerDrawable.getBounds();
Drawable buttonDrawable = view.getResources().getDrawable(R.drawable.map_zoom_in);
bounds.right = (int) (view.getWidth() - 7 * scaleCoefficient);
bounds.bottom = (int) (view.getHeight() - buttonDrawable.getMinimumHeight());
bounds.bottom = (int) (view.getHeight() - (!zoomControls.isVisible() ? 0 : zoomControls.getHeight()));
bounds.top = bounds.bottom - rulerDrawable.getMinimumHeight();
bounds.left = bounds.right - cacheRulerDistPix;
rulerDrawable.setBounds(bounds);
@ -550,7 +234,4 @@ public class MapControlsLayer extends OsmandMapLayer {
}
}
}

View file

@ -0,0 +1,64 @@
package net.osmand.plus.views.controls;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import android.graphics.Canvas;
import android.graphics.PointF;
import android.os.Handler;
import android.widget.FrameLayout;
public abstract class MapControls {
protected MapActivity mapActivity;
protected float scaleCoefficient;
protected Handler showUIHandler;
protected int shadowColor;
private boolean visible;
public MapControls(MapActivity mapActivity, Handler showUIHandler, float scaleCoefficient) {
this.mapActivity = mapActivity;
this.showUIHandler = showUIHandler;
this.scaleCoefficient = scaleCoefficient;
}
public void setShadowColor(int textColor, int shadowColor) {
this.shadowColor = shadowColor;
}
public final void init(FrameLayout layout) {
initControls(layout);
}
public final void show(FrameLayout layout) {
visible = true;
showControls(layout);
}
public final void hide(FrameLayout layout) {
visible = false;
hideControls(layout);
}
public boolean isVisible() {
return visible;
}
protected void initControls(FrameLayout layout) {
}
public abstract int getWidth();
protected abstract void hideControls(FrameLayout layout);
protected abstract void showControls(FrameLayout layout);
public abstract void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings nightMode);
public boolean onSingleTap(PointF point, RotatedTileBox tileBox) {
return false;
}
}

View file

@ -0,0 +1,72 @@
package net.osmand.plus.views.controls;
import gnu.trove.list.array.TIntArrayList;
import java.util.ArrayList;
import java.util.List;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.views.OsmandMapTileView;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.view.View;
public class MapMagnifier {
public static View.OnLongClickListener getOnClickMagnifierListener(final OsmandMapTileView view) {
final View.OnLongClickListener listener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View notUseCouldBeNull) {
final OsmandSettings.OsmandPreference<Float> zoomScale = view.getSettings().MAP_ZOOM_SCALE_BY_DENSITY;
final AlertDialog.Builder bld = new AlertDialog.Builder(view.getContext());
float scale = view.getZoomScale();
int p = (int) ((scale > 0 ? 1 : -1) * Math.round(scale * scale * 100)) + 100;
final TIntArrayList tlist = new TIntArrayList(new int[] { 75, 100, 150, 200, 300, 400, 500 });
final List<String> values = new ArrayList<String>();
int i = -1;
for (int k = 0; k <= tlist.size(); k++) {
final boolean end = k == tlist.size();
if (i == -1) {
if ((end || p < tlist.get(k))) {
values.add(p + "%");
i = k;
} else if (p == tlist.get(k)) {
i = k;
}
}
if (k < tlist.size()) {
values.add(tlist.get(k) + "%");
}
}
if (values.size() != tlist.size()) {
tlist.insert(i, p);
}
bld.setTitle(R.string.map_magnifier);
bld.setSingleChoiceItems(values.toArray(new String[values.size()]), i,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int p = tlist.get(which);
float newScale;
if (p >= 100) {
newScale = (float) Math.sqrt((tlist.get(which) - 100f) / 100f);
} else {
newScale = -(float) Math.sqrt((100f - tlist.get(which)) / 100f);
}
zoomScale.set(newScale - (float) Math.sqrt(Math.max(view.getDensity() - 1, 0)));
view.getAnimatedDraggingThread().startZooming(view.getZoom(),
view.getSettingsZoomScale(), false);
dialog.dismiss();
}
});
bld.show();
return true;
}
};
return listener;
}
}

View file

@ -0,0 +1,144 @@
package net.osmand.plus.views.controls;
import java.util.List;
import net.londatiga.android.ActionItem;
import net.londatiga.android.QuickAction;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.FrameLayout;
public class MapMenuControls extends MapControls {
private Button backToMenuButton;
private Drawable modeShadow;
private Drawable cacheAppModeIcon = null;
private ApplicationMode cacheApplicationMode = null;
public MapMenuControls(MapActivity mapActivity, Handler showUIHandler, float scaleCoefficient) {
super(mapActivity, showUIHandler, scaleCoefficient);
}
private void initBackToMenuButton(final OsmandMapTileView view, FrameLayout parent) {
android.widget.FrameLayout.LayoutParams params;
Context ctx = view.getContext();
backToMenuButton = new Button(ctx);
backToMenuButton.setContentDescription(ctx.getString(R.string.backToMenu));
backToMenuButton.setBackgroundResource(R.drawable.map_btn_menu);
params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM | Gravity.LEFT);
parent.addView(backToMenuButton, params);
backToMenuButton.setEnabled(true);
modeShadow = view.getResources().getDrawable(R.drawable.zoom_background);
backToMenuButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// double lat = activity.getMapView().getLatitude();
// double lon = activity.getMapView().getLongitude();
// MainMenuActivity.backToMainMenuDialog(activity, new LatLon(lat, lon));
mapActivity.getMapActions().openOptionsMenuAsList();
}
});
mapActivity.accessibleContent.add(backToMenuButton);
}
@Override
public void showControls(FrameLayout layout) {
initBackToMenuButton(mapActivity.getMapView(), layout);
}
@Override
public int getWidth() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void hideControls(FrameLayout layout) {
mapActivity.accessibleContent.remove(backToMenuButton);
}
@Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings nightMode) {
drawApplicationMode(canvas, nightMode != null && nightMode.isNightMode());
}
private void drawApplicationMode(Canvas canvas, boolean nightMode) {
OsmandMapTileView view = mapActivity.getMapView();
ApplicationMode appMode = view.getSettings().getApplicationMode();
if(appMode != cacheApplicationMode){
modeShadow.setBounds(backToMenuButton.getLeft() + (int) (2 * scaleCoefficient), backToMenuButton.getTop() - (int) (24 * scaleCoefficient),
backToMenuButton.getRight() - (int) (4 * scaleCoefficient), backToMenuButton.getBottom());
cacheAppModeIcon = view.getResources().getDrawable(appMode.getSmallIcon(nightMode));
int l = modeShadow.getBounds().left + (modeShadow.getBounds().width() - cacheAppModeIcon.getMinimumWidth()) / 2;
int t = (int) (modeShadow.getBounds().top + 2 * scaleCoefficient);
cacheAppModeIcon.setBounds(l, t, l + cacheAppModeIcon.getMinimumWidth(), t + cacheAppModeIcon.getMinimumHeight());
}
modeShadow.draw(canvas);
if(cacheAppModeIcon != null){
cacheAppModeIcon.draw(canvas);
}
}
@Override
public boolean onSingleTap(PointF point, RotatedTileBox tileBox) {
if (modeShadow.getBounds().contains((int) point.x, (int) point.y)) {
onApplicationModePress();
return true;
}
return false;
}
private void onApplicationModePress() {
final QuickAction mQuickAction = new QuickAction(backToMenuButton);
List<ApplicationMode> vls = ApplicationMode.values(mapActivity.getMyApplication().getSettings());
final ApplicationMode[] modes = vls.toArray(new ApplicationMode[vls.size()]);
int[] icons = new int[vls.size()];
int[] values = new int[vls.size()];
for(int k = 0; k < modes.length; k++) {
icons[k] = modes[k].getSmallIcon(false);
values[k] = modes[k].getStringResource();
}
for (int i = 0; i < modes.length; i++) {
final ActionItem action = new ActionItem();
action.setTitle(mapActivity.getResources().getString(values[i]));
action.setIcon(mapActivity.getResources().getDrawable(icons[i]));
final int j = i;
action.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mapActivity.getMyApplication().getSettings().APPLICATION_MODE.set(modes[j]);
mQuickAction.dismiss();
}
});
mQuickAction.addActionItem(action);
}
mQuickAction.setAnimStyle(QuickAction.ANIM_AUTO);
mQuickAction.show();
}
}

View file

@ -0,0 +1,238 @@
package net.osmand.plus.views.controls;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.OsmAndConstants;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.views.BaseMapLayer;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.ShadowText;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.text.TextPaint;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.FrameLayout;
public class MapZoomControls extends MapControls {
private static final int SHOW_ZOOM_LEVEL_MSG_ID = OsmAndConstants.UI_HANDLER_MAP_CONTROLS + 1;
private static final int SHOW_ZOOM_BUTTON_MSG_ID = OsmAndConstants.UI_HANDLER_MAP_CONTROLS + 2;
private static final int SHOW_ZOOM_LEVEL_DELAY = 1000;
private static final int SHOW_ZOOM_LEVEL_BUTTON_DELAY = 1500;
private Button zoomInButton;
private Button zoomOutButton;
private TextPaint zoomTextPaint;
private Drawable zoomShadow;
private Bitmap mapMagnifier;
private Paint bitmapPaint;
private boolean showZoomLevel = false;
private boolean showZoomLevelButton = false;
private OsmandMapTileView view;
public MapZoomControls(MapActivity mapActivity, Handler showUIHandler, float scaleCoefficient) {
super(mapActivity, showUIHandler, scaleCoefficient);
view = mapActivity.getMapView();
}
public boolean onSingleTap(PointF point, RotatedTileBox tileBox) {
if (isShowZoomLevel() && zoomShadow.getBounds().contains((int) point.x, (int) point.y)) {
MapMagnifier.getOnClickMagnifierListener(view).onLongClick(null);
return true;
}
return false;
}
@Override
protected void showControls(FrameLayout parent) {
int minimumWidth = view.getResources().getDrawable(R.drawable.map_zoom_in).getMinimumWidth();
Context ctx = view.getContext();
zoomInButton = new Button(ctx);
zoomInButton.setBackgroundResource(R.drawable.map_zoom_in);
android.widget.FrameLayout.LayoutParams params =
new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.BOTTOM
| Gravity.RIGHT);
params.setMargins(0, 0, 0, 0);
zoomInButton.setContentDescription(ctx.getString(R.string.zoomIn));
parent.addView(zoomInButton, params);
zoomOutButton = new Button(ctx);
zoomOutButton.setBackgroundResource(R.drawable.map_zoom_out);
params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.BOTTOM
| Gravity.RIGHT);
params.setMargins(0, 0, minimumWidth, 0);
zoomOutButton.setContentDescription(ctx.getString(R.string.zoomOut));
parent.addView(zoomOutButton, params);
mapActivity.accessibleContent.add(zoomInButton);
mapActivity.accessibleContent.add(zoomOutButton);
zoomInButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (view.isZooming()) {
mapActivity.changeZoom(2);
} else {
mapActivity.changeZoom(1);
}
}
});
final View.OnLongClickListener listener = MapMagnifier.getOnClickMagnifierListener(view);
zoomInButton.setOnLongClickListener(listener);
zoomOutButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mapActivity.changeZoom(-1);
}
});
zoomOutButton.setOnLongClickListener(listener);
}
@Override
public void initControls(FrameLayout parent) {
zoomTextPaint = new TextPaint();
zoomTextPaint.setTextSize(18 * scaleCoefficient);
zoomTextPaint.setAntiAlias(true);
zoomTextPaint.setFakeBoldText(true);
zoomShadow = view.getResources().getDrawable(R.drawable.zoom_background).mutate();
mapMagnifier = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_magnifier);
bitmapPaint = new Paint();
}
@Override
public int getWidth() {
return 0; // TODO
}
@Override
public void hideControls(FrameLayout layout) {
mapActivity.accessibleContent.remove(zoomInButton);
mapActivity.accessibleContent.remove(zoomOutButton);
}
private void drawZoomLevel(Canvas canvas, RotatedTileBox tb, boolean drawZoomLevel) {
if (zoomShadow.getBounds().width() == 0) {
zoomShadow.setBounds(zoomInButton.getLeft() - 2, zoomInButton.getTop() - (int) (18 * scaleCoefficient),
zoomInButton.getRight(), zoomInButton.getBottom());
}
zoomShadow.draw(canvas);
if (drawZoomLevel) {
String zoomText = tb.getZoom() + "";
float frac = tb.getZoomScale();
if (frac != 0) {
int ifrac = (int) (frac * 10);
boolean pos = ifrac > 0;
zoomText += (pos ? "+" : "-");
zoomText += Math.abs(ifrac) / 10;
if (ifrac % 10 != 0) {
zoomText += "." + Math.abs(ifrac) % 10;
}
}
float length = zoomTextPaint.measureText(zoomText);
ShadowText.draw(zoomText, canvas, zoomInButton.getLeft() + (zoomInButton.getWidth() - length - 2) / 2,
zoomInButton.getTop() + 4 * scaleCoefficient, zoomTextPaint, shadowColor);
} else {
int size = (int) (16 * scaleCoefficient);
int top = (int) (zoomInButton.getTop() - size - 4 * scaleCoefficient);
int left = (int) (zoomInButton.getLeft() + (zoomInButton.getWidth() - mapMagnifier.getWidth() - 2 * scaleCoefficient) / 2);
// canvas density /2 ? size * 2
canvas.drawBitmap(mapMagnifier, null, new Rect(left, top, left + size * 2, top + size * 2), bitmapPaint);
}
}
@Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings nightMode) {
BaseMapLayer mainLayer = view.getMainLayer();
boolean zoomInEnabled = mainLayer != null && tileBox.getZoom() < mainLayer.getMaximumShownMapZoom();
boolean zoomOutEnabled = mainLayer != null && tileBox.getZoom() > mainLayer.getMinimumShownMapZoom();
if (zoomInButton.isEnabled() != zoomInEnabled) {
zoomInButton.setEnabled(zoomInEnabled);
}
if (zoomOutButton.isEnabled() != zoomOutEnabled) {
zoomOutButton.setEnabled(zoomOutEnabled);
}
if (view.isZooming()) {
showZoomLevel = true;
showZoomLevelButton = false;
showUIHandler.removeMessages(SHOW_ZOOM_LEVEL_MSG_ID);
showUIHandler.removeMessages(SHOW_ZOOM_BUTTON_MSG_ID);
} else {
if (isShowZoomLevel() && view.getSettings().SHOW_RULER.get()) {
hideZoomLevelInTime();
}
}
boolean drawZoomLevel = isShowZoomLevel() || !view.getSettings().SHOW_RULER.get();
if (drawZoomLevel) {
drawZoomLevel(canvas, tileBox, !showZoomLevelButton);
}
}
private void sendMessageToShowZoomLevel() {
Message msg = Message.obtain(showUIHandler, new Runnable() {
@Override
public void run() {
showZoomLevelButton = true;
sendMessageToShowZoomButton();
view.refreshMap();
}
});
msg.what = SHOW_ZOOM_LEVEL_MSG_ID;
showUIHandler.sendMessageDelayed(msg, SHOW_ZOOM_LEVEL_DELAY);
}
private void sendMessageToShowZoomButton() {
Message msg = Message.obtain(showUIHandler, new Runnable() {
@Override
public void run() {
showZoomLevelButton = false;
showZoomLevel = false;
view.refreshMap();
}
});
msg.what = SHOW_ZOOM_BUTTON_MSG_ID;
showUIHandler.sendMessageDelayed(msg, SHOW_ZOOM_LEVEL_BUTTON_DELAY);
}
private void hideZoomLevelInTime() {
if (!showUIHandler.hasMessages(SHOW_ZOOM_LEVEL_MSG_ID) && !showUIHandler.hasMessages(SHOW_ZOOM_BUTTON_MSG_ID)) {
sendMessageToShowZoomLevel();
}
}
@Override
public void setShadowColor(int textColor, int shadowColor) {
super.setShadowColor(textColor, shadowColor);
zoomTextPaint.setColor(textColor);
}
public boolean isShowZoomLevel() {
return showZoomLevel;
}
public int getHeight() {
Drawable buttonDrawable = view.getResources().getDrawable(R.drawable.map_zoom_in);
return buttonDrawable.getMinimumHeight();
}
}