Merge pull request #711 from Bars107/master

fixed bug OsmAnd-androidAND-85 in Jira. One click with 2 fingers, automa...
This commit is contained in:
vshcherb 2014-06-24 15:23:51 +02:00
commit 2be802e7f2
2 changed files with 156 additions and 87 deletions

View file

@ -0,0 +1,50 @@
package net.osmand.plus.helpers;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
/**
* Created by Barsik on 24.06.2014.
*/
public abstract class SimpleTwoFingerTapDetector {
private static final int TIMEOUT = ViewConfiguration.getDoubleTapTimeout() + 100;
private long mFirstDownTime = 0;
private byte mTwoFingerTapCount = 0;
private MotionEvent firstEvent = null;
private void reset(long time) {
mFirstDownTime = time;
mTwoFingerTapCount = 0;
}
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
if (mFirstDownTime == 0 || event.getEventTime() - mFirstDownTime > TIMEOUT){
reset(event.getDownTime());
}
break;
case MotionEvent.ACTION_POINTER_UP:
if (event.getPointerCount() == 2) {
mTwoFingerTapCount++;
firstEvent = MotionEvent.obtain(event);
}
else{
mFirstDownTime = 0;
firstEvent = null;
}
break;
case MotionEvent.ACTION_UP:
if (mTwoFingerTapCount == 1 && event.getEventTime() - mFirstDownTime < TIMEOUT) {
onTwoFingerTap(firstEvent, event);
mFirstDownTime = 0;
firstEvent = null;
return true;
}
}
return false;
}
public abstract void onTwoFingerTap(MotionEvent firstevent, MotionEvent secondevent);
}

View file

@ -6,6 +6,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import android.view.*;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.access.AccessibilityActionsProvider; import net.osmand.access.AccessibilityActionsProvider;
import net.osmand.access.AccessibleToast; import net.osmand.access.AccessibleToast;
@ -22,6 +23,7 @@ import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings; import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.helpers.SimpleTwoFingerTapDetector;
import net.osmand.plus.views.MultiTouchSupport.MultiTouchZoomListener; import net.osmand.plus.views.MultiTouchSupport.MultiTouchZoomListener;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
@ -42,15 +44,9 @@ import android.os.Message;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener; import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener; import android.view.GestureDetector.OnGestureListener;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback; import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.Toast; import android.widget.Toast;
public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCallback, Callback { public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCallback, Callback {
@ -62,12 +58,13 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
private boolean MEASURE_FPS = false; private boolean MEASURE_FPS = false;
private FPSMeasurement main = new FPSMeasurement(); private FPSMeasurement main = new FPSMeasurement();
private FPSMeasurement additional = new FPSMeasurement(); private FPSMeasurement additional = new FPSMeasurement();
private class FPSMeasurement { private class FPSMeasurement {
int fpsMeasureCount = 0; int fpsMeasureCount = 0;
int fpsMeasureMs = 0; int fpsMeasureMs = 0;
long fpsFirstMeasurement = 0; long fpsFirstMeasurement = 0;
float fps; float fps;
void calculateFPS(long start, long end) { void calculateFPS(long start, long end) {
fpsMeasureMs += end - start; fpsMeasureMs += end - start;
fpsMeasureCount++; fpsMeasureCount++;
@ -79,10 +76,10 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
} }
} }
} }
protected static final int emptyTileDivisor = 16; protected static final int emptyTileDivisor = 16;
public interface OnTrackBallListener { public interface OnTrackBallListener {
public boolean onTrackBallEvent(MotionEvent e); public boolean onTrackBallEvent(MotionEvent e);
@ -97,10 +94,10 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
} }
protected static final Log log = PlatformUtil.getLog(OsmandMapTileView.class); protected static final Log log = PlatformUtil.getLog(OsmandMapTileView.class);
private RotatedTileBox currentViewport; private RotatedTileBox currentViewport;
private float rotate; // accumulate private float rotate; // accumulate
private int mapPosition; private int mapPosition;
@ -118,14 +115,14 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
private AccessibilityActionsProvider accessibilityActions; private AccessibilityActionsProvider accessibilityActions;
private List<OsmandMapLayer> layers = new ArrayList<OsmandMapLayer>(); private List<OsmandMapLayer> layers = new ArrayList<OsmandMapLayer>();
private BaseMapLayer mainLayer; private BaseMapLayer mainLayer;
private Map<OsmandMapLayer, Float> zOrders = new HashMap<OsmandMapLayer, Float>(); private Map<OsmandMapLayer, Float> zOrders = new HashMap<OsmandMapLayer, Float>();
// UI Part // UI Part
// handler to refresh map (in ui thread - ui thread is not necessary, but msg queue is required). // handler to refresh map (in ui thread - ui thread is not necessary, but msg queue is required).
protected Handler handler ; protected Handler handler;
private Handler baseHandler; private Handler baseHandler;
private AnimateDraggingMapThread animatedDraggingThread; private AnimateDraggingMapThread animatedDraggingThread;
@ -142,21 +139,35 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
private DisplayMetrics dm; private DisplayMetrics dm;
private final OsmandApplication application; private final OsmandApplication application;
protected OsmandSettings settings = null; protected OsmandSettings settings = null;
private Bitmap bufferBitmap; private Bitmap bufferBitmap;
private RotatedTileBox bufferImgLoc; private RotatedTileBox bufferImgLoc;
private Bitmap bufferBitmapTmp; private Bitmap bufferBitmapTmp;
private Paint paintImg; private Paint paintImg;
private boolean afterTwoFingerTap = false;
SimpleTwoFingerTapDetector twoFingerTapDetector = new SimpleTwoFingerTapDetector() {
@Override
public void onTwoFingerTap(MotionEvent firstevent, MotionEvent secondevent) {
afterTwoFingerTap = true;
final RotatedTileBox tb = getCurrentRotatedTileBox();
float midx = (firstevent.getX() + secondevent.getX()) / 2;
float midy = (firstevent.getY() + secondevent.getY()) / 2;
final double lat = tb.getLatFromPixel(midx, midy);
final double lon = tb.getLonFromPixel(midx, midy);
getAnimatedDraggingThread().startMoving(lat, lon, getZoom() - 1, true);
}
};
public OsmandMapTileView(Context context, AttributeSet attrs) { public OsmandMapTileView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
application = (OsmandApplication) context.getApplicationContext(); application = (OsmandApplication) context.getApplicationContext();
initView(); initView();
} }
public OsmandMapTileView(Context context) { public OsmandMapTileView(Context context) {
@ -172,8 +183,8 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
paintGrayFill.setStyle(Style.FILL); paintGrayFill.setStyle(Style.FILL);
// when map rotate // when map rotate
paintGrayFill.setAntiAlias(true); paintGrayFill.setAntiAlias(true);
paintBlackFill= new Paint(); paintBlackFill = new Paint();
paintBlackFill.setColor(Color.BLACK); paintBlackFill.setColor(Color.BLACK);
paintBlackFill.setStyle(Style.FILL); paintBlackFill.setStyle(Style.FILL);
// when map rotate // when map rotate
@ -190,7 +201,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
paintCenter.setColor(Color.rgb(60, 60, 60)); paintCenter.setColor(Color.rgb(60, 60, 60));
paintCenter.setStrokeWidth(2); paintCenter.setStrokeWidth(2);
paintCenter.setAntiAlias(true); paintCenter.setAntiAlias(true);
paintImg = new Paint(); paintImg = new Paint();
paintImg.setFilterBitmap(true); paintImg.setFilterBitmap(true);
// paintImg.setDither(true); // paintImg.setDither(true);
@ -201,7 +212,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
handler = new Handler(); handler = new Handler();
baseHandler = new Handler(application.getResourceManager().getRenderingBufferImageThread().getLooper()); baseHandler = new Handler(application.getResourceManager().getRenderingBufferImageThread().getLooper());
getHolder().addCallback(this); getHolder().addCallback(this);
animatedDraggingThread = new AnimateDraggingMapThread(this); animatedDraggingThread = new AnimateDraggingMapThread(this);
@ -215,7 +226,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
currentViewport = new RotatedTileBox.RotatedTileBoxBuilder(). currentViewport = new RotatedTileBox.RotatedTileBoxBuilder().
setLocation(0, 0).setZoomAndScale(3, 0).setPixelDimensions(getWidth(), getHeight()).build(); setLocation(0, 0).setZoomAndScale(3, 0).setPixelDimensions(getWidth(), getHeight()).build();
currentViewport.setDensity(dm.density); currentViewport.setDensity(dm.density);
} }
@Override @Override
@ -236,14 +247,14 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
public boolean onKeyDown(int keyCode, KeyEvent event) { public boolean onKeyDown(int keyCode, KeyEvent event) {
return application.accessibilityEnabled() ? false : super.onKeyDown(keyCode, event); return application.accessibilityEnabled() ? false : super.onKeyDown(keyCode, event);
} }
public boolean isLayerVisible(OsmandMapLayer layer) { public boolean isLayerVisible(OsmandMapLayer layer) {
return layers.contains(layer); return layers.contains(layer);
} }
public float getZorder(OsmandMapLayer layer) { public float getZorder(OsmandMapLayer layer) {
Float z = zOrders.get(layer); Float z = zOrders.get(layer);
if(z == null) { if (z == null) {
return 10; return 10;
} }
return z; return z;
@ -262,7 +273,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
} }
public synchronized void removeLayer(OsmandMapLayer layer) { public synchronized void removeLayer(OsmandMapLayer layer) {
while(layers.remove(layer)); while (layers.remove(layer)) ;
zOrders.remove(layer); zOrders.remove(layer);
layer.destroyLayer(); layer.destroyLayer();
} }
@ -270,11 +281,11 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
public List<OsmandMapLayer> getLayers() { public List<OsmandMapLayer> getLayers() {
return layers; return layers;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T extends OsmandMapLayer> T getLayerByClass(Class<T> cl) { public <T extends OsmandMapLayer> T getLayerByClass(Class<T> cl) {
for(OsmandMapLayer lr : layers) { for (OsmandMapLayer lr : layers) {
if(cl.isInstance(lr)){ if (cl.isInstance(lr)) {
return (T) lr; return (T) lr;
} }
} }
@ -290,7 +301,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
if (mainLayer != null && zoom <= mainLayer.getMaximumShownMapZoom() && zoom >= mainLayer.getMinimumShownMapZoom()) { if (mainLayer != null && zoom <= mainLayer.getMaximumShownMapZoom() && zoom >= mainLayer.getMinimumShownMapZoom()) {
animatedDraggingThread.stopAnimating(); animatedDraggingThread.stopAnimating();
currentViewport.setZoomAndAnimation(zoom, 0); currentViewport.setZoomAndAnimation(zoom, 0);
currentViewport.setRotate(zoom > LOWEST_ZOOM_TO_ROTATE ? rotate : 0 ); currentViewport.setRotate(zoom > LOWEST_ZOOM_TO_ROTATE ? rotate : 0);
refreshMap(); refreshMap();
} }
} }
@ -299,13 +310,13 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
if (mainLayer != null && zoom <= mainLayer.getMaximumShownMapZoom() && zoom >= mainLayer.getMinimumShownMapZoom()) { if (mainLayer != null && zoom <= mainLayer.getMaximumShownMapZoom() && zoom >= mainLayer.getMinimumShownMapZoom()) {
animatedDraggingThread.stopAnimating(); animatedDraggingThread.stopAnimating();
currentViewport.setZoom(zoom, scale, 0); currentViewport.setZoom(zoom, scale, 0);
currentViewport.setRotate(zoom > LOWEST_ZOOM_TO_ROTATE ? rotate : 0 ); currentViewport.setRotate(zoom > LOWEST_ZOOM_TO_ROTATE ? rotate : 0);
refreshMap(); refreshMap();
} }
} }
public boolean isMapRotateEnabled(){ public boolean isMapRotateEnabled() {
return getZoom() > LOWEST_ZOOM_TO_ROTATE; return getZoom() > LOWEST_ZOOM_TO_ROTATE;
} }
@ -349,18 +360,18 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
return currentViewport.getZoom(); return currentViewport.getZoom();
} }
public float getSettingsZoomScale(){ public float getSettingsZoomScale() {
return settings.getSettingsZoomScale(getDensity()); return settings.getSettingsZoomScale(getDensity());
} }
public float getZoomScale() { public float getZoomScale() {
return currentViewport.getZoomScale(); return currentViewport.getZoomScale();
} }
public boolean isZooming(){ public boolean isZooming() {
return currentViewport.isZoomAnimated(); return currentViewport.isZoomAnimated();
} }
public void setMapLocationListener(IMapLocationListener l) { public void setMapLocationListener(IMapLocationListener l) {
locationListener = l; locationListener = l;
} }
@ -376,7 +387,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
public BaseMapLayer getMainLayer() { public BaseMapLayer getMainLayer() {
return mainLayer; return mainLayer;
} }
public void setMainLayer(BaseMapLayer mainLayer) { public void setMainLayer(BaseMapLayer mainLayer) {
this.mainLayer = mainLayer; this.mainLayer = mainLayer;
int zoom = currentViewport.getZoom(); int zoom = currentViewport.getZoom();
@ -393,21 +404,21 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
public void setMapPosition(int type) { public void setMapPosition(int type) {
this.mapPosition = type; this.mapPosition = type;
} }
public OsmandSettings getSettings(){ public OsmandSettings getSettings() {
if(settings == null){ if (settings == null) {
settings = getApplication().getSettings(); settings = getApplication().getSettings();
} }
return settings; return settings;
} }
private void drawBasemap(Canvas canvas) { private void drawBasemap(Canvas canvas) {
if(bufferImgLoc != null) { if (bufferImgLoc != null) {
float rot = - bufferImgLoc.getRotate(); float rot = -bufferImgLoc.getRotate();
canvas.rotate(rot, currentViewport.getCenterPixelX(), currentViewport.getCenterPixelY()); canvas.rotate(rot, currentViewport.getCenterPixelX(), currentViewport.getCenterPixelY());
final RotatedTileBox calc = currentViewport.copy(); final RotatedTileBox calc = currentViewport.copy();
calc.setRotate(bufferImgLoc.getRotate()); calc.setRotate(bufferImgLoc.getRotate());
int cz = getZoom(); int cz = getZoom();
QuadPointDouble lt = bufferImgLoc.getLeftTopTile(cz); QuadPointDouble lt = bufferImgLoc.getLeftTopTile(cz);
QuadPointDouble rb = bufferImgLoc.getRightBottomTile(cz); QuadPointDouble rb = bufferImgLoc.getRightBottomTile(cz);
@ -415,19 +426,19 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
final float x2 = calc.getPixXFromTile(rb.x, rb.y, cz); final float x2 = calc.getPixXFromTile(rb.x, rb.y, cz);
final float y1 = calc.getPixYFromTile(lt.x, lt.y, cz); final float y1 = calc.getPixYFromTile(lt.x, lt.y, cz);
final float y2 = calc.getPixYFromTile(rb.x, rb.y, cz); final float y2 = calc.getPixYFromTile(rb.x, rb.y, cz);
if(!bufferBitmap.isRecycled()){ if (!bufferBitmap.isRecycled()) {
RectF rct = new RectF(x1, y1, x2, y2); RectF rct = new RectF(x1, y1, x2, y2);
canvas.drawBitmap(bufferBitmap, null, rct, paintImg); canvas.drawBitmap(bufferBitmap, null, rct, paintImg);
} }
canvas.rotate(-rot, currentViewport.getCenterPixelX(), currentViewport.getCenterPixelY()); canvas.rotate(-rot, currentViewport.getCenterPixelX(), currentViewport.getCenterPixelY());
} }
} }
private void refreshBaseMapInternal(RotatedTileBox tileBox, DrawSettings drawSettings) { private void refreshBaseMapInternal(RotatedTileBox tileBox, DrawSettings drawSettings) {
if(tileBox.getPixHeight() == 0 || tileBox.getPixWidth() == 0){ if (tileBox.getPixHeight() == 0 || tileBox.getPixWidth() == 0) {
return; return;
} }
if(bufferBitmapTmp == null || tileBox.getPixHeight() != bufferBitmapTmp.getHeight() if (bufferBitmapTmp == null || tileBox.getPixHeight() != bufferBitmapTmp.getHeight()
|| tileBox.getPixWidth() != bufferBitmapTmp.getWidth()) { || tileBox.getPixWidth() != bufferBitmapTmp.getWidth()) {
bufferBitmapTmp = Bitmap.createBitmap(tileBox.getPixWidth(), tileBox.getPixHeight(), Config.RGB_565); bufferBitmapTmp = Bitmap.createBitmap(tileBox.getPixWidth(), tileBox.getPixHeight(), Config.RGB_565);
} }
@ -453,7 +464,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
synchronized (this) { synchronized (this) {
bufferImgLoc = tileBox; bufferImgLoc = tileBox;
bufferBitmap = bufferBitmapTmp; bufferBitmap = bufferBitmapTmp;
bufferBitmapTmp = t; bufferBitmapTmp = t;
} }
long end = SystemClock.elapsedRealtime(); long end = SystemClock.elapsedRealtime();
additional.calculateFPS(start, end); additional.calculateFPS(start, end);
@ -466,9 +477,9 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
Canvas canvas = holder.lockCanvas(); Canvas canvas = holder.lockCanvas();
if (canvas != null) { if (canvas != null) {
try { try {
final float ratioy = mapPosition == OsmandSettings.BOTTOM_CONSTANT ? 0.85f : 0.5f; final float ratioy = mapPosition == OsmandSettings.BOTTOM_CONSTANT ? 0.85f : 0.5f;
final int cy = (int) (ratioy * getHeight()); final int cy = (int) (ratioy * getHeight());
if(currentViewport.getPixWidth() != getWidth() || currentViewport.getPixHeight() != getHeight() || if (currentViewport.getPixWidth() != getWidth() || currentViewport.getPixHeight() != getHeight() ||
currentViewport.getCenterPixelY() != cy) { currentViewport.getCenterPixelY() != cy) {
currentViewport.setPixelDimensions(getWidth(), getHeight(), 0.5f, ratioy); currentViewport.setPixelDimensions(getWidth(), getHeight(), 0.5f, ratioy);
refreshBufferImage(drawSettings); refreshBufferImage(drawSettings);
@ -499,18 +510,19 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
public boolean isMeasureFPS() { public boolean isMeasureFPS() {
return MEASURE_FPS; return MEASURE_FPS;
} }
public void setMeasureFPS(boolean measureFPS) { public void setMeasureFPS(boolean measureFPS) {
MEASURE_FPS = measureFPS; MEASURE_FPS = measureFPS;
} }
public float getFPS(){ public float getFPS() {
return main.fps; return main.fps;
} }
public float getSecondaryFPS(){
public float getSecondaryFPS() {
return additional.fps; return additional.fps;
} }
private void drawOverMap(Canvas canvas, RotatedTileBox tileBox, DrawSettings drawSettings) { private void drawOverMap(Canvas canvas, RotatedTileBox tileBox, DrawSettings drawSettings) {
final QuadPoint c = tileBox.getCenterPixelPoint(); final QuadPoint c = tileBox.getCenterPixelPoint();
synchronized (this) { synchronized (this) {
@ -558,7 +570,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
} }
refreshBaseMapInternal(currentViewport.copy(), param); refreshBaseMapInternal(currentViewport.copy(), param);
sendRefreshMapMsg(param, 0); sendRefreshMapMsg(param, 0);
} catch(Exception e) { } catch (Exception e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
} }
} }
@ -573,7 +585,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
public void refreshMap() { public void refreshMap() {
refreshMap(false); refreshMap(false);
} }
// this method could be called in non UI thread // this method could be called in non UI thread
public void refreshMap(final boolean updateVectorRendering) { public void refreshMap(final boolean updateVectorRendering) {
if (isShown()) { if (isShown()) {
@ -591,7 +603,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
public void run() { public void run() {
DrawSettings param = drawSettings; DrawSettings param = drawSettings;
handler.removeMessages(MAP_REFRESH_MESSAGE); handler.removeMessages(MAP_REFRESH_MESSAGE);
refreshMapInternal(param); refreshMapInternal(param);
} }
}); });
@ -630,6 +642,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
} }
return scaleCoefficient; return scaleCoefficient;
} }
/** /**
* These methods do not consider rotating * These methods do not consider rotating
*/ */
@ -649,7 +662,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
refreshMap(); refreshMap();
} }
} }
protected void setLatLonAnimate(double latitude, double longitude, boolean notify) { protected void setLatLonAnimate(double latitude, double longitude, boolean notify) {
currentViewport.setLatLonCenter(latitude, longitude); currentViewport.setLatLonCenter(latitude, longitude);
refreshMap(); refreshMap();
@ -665,12 +678,12 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
locationListener.locationChanged(getLatitude(), getLongitude(), this); locationListener.locationChanged(getLatitude(), getLongitude(), this);
} }
} }
// for internal usage // for internal usage
protected void zoomToAnimate(float tzoom, boolean notify) { protected void zoomToAnimate(float tzoom, boolean notify) {
int zoom = getZoom(); int zoom = getZoom();
float zoomToAnimate = tzoom - zoom - getZoomScale(); float zoomToAnimate = tzoom - zoom - getZoomScale();
if(zoomToAnimate >= 1) { if (zoomToAnimate >= 1) {
zoom += (int) zoomToAnimate; zoom += (int) zoomToAnimate;
zoomToAnimate -= (int) zoomToAnimate; zoomToAnimate -= (int) zoomToAnimate;
} }
@ -679,8 +692,8 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
zoomToAnimate += 1; zoomToAnimate += 1;
} }
if (mainLayer != null && mainLayer.getMaximumShownMapZoom() >= zoom && mainLayer.getMinimumShownMapZoom() <= zoom) { if (mainLayer != null && mainLayer.getMaximumShownMapZoom() >= zoom && mainLayer.getMinimumShownMapZoom() <= zoom) {
currentViewport.setZoomAndAnimation(zoom, zoomToAnimate); currentViewport.setZoomAndAnimation(zoom, zoomToAnimate);
currentViewport.setRotate(zoom > LOWEST_ZOOM_TO_ROTATE ? rotate : 0 ); currentViewport.setRotate(zoom > LOWEST_ZOOM_TO_ROTATE ? rotate : 0);
refreshMap(); refreshMap();
if (notify && locationListener != null) { if (notify && locationListener != null) {
locationListener.locationChanged(getLatitude(), getLongitude(), this); locationListener.locationChanged(getLatitude(), getLongitude(), this);
@ -699,16 +712,21 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
if (twoFingerTapDetector.onTouchEvent(event)) {
return true;
}
if (event.getAction() == MotionEvent.ACTION_DOWN) { if (event.getAction() == MotionEvent.ACTION_DOWN) {
animatedDraggingThread.stopAnimating(); animatedDraggingThread.stopAnimating();
} }
for(int i=layers.size() - 1; i >= 0; i--) { for (int i = layers.size() - 1; i >= 0; i--) {
if(layers.get(i).onTouchEvent(event, getCurrentRotatedTileBox())) { if (layers.get(i).onTouchEvent(event, getCurrentRotatedTileBox())) {
return true; return true;
} }
} }
if (!multiTouchSupport.onTouchEvent(event)) { if (!multiTouchSupport.onTouchEvent(event)) {
/* return */gestureDetector.onTouchEvent(event); /* return */
gestureDetector.onTouchEvent(event);
} }
return true; return true;
} }
@ -738,7 +756,6 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
} }
public AnimateDraggingMapThread getAnimatedDraggingThread() { public AnimateDraggingMapThread getAnimatedDraggingThread() {
return animatedDraggingThread; return animatedDraggingThread;
} }
@ -752,7 +769,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
}); });
} }
private class MapTileViewMultiTouchZoomListener implements MultiTouchZoomListener { private class MapTileViewMultiTouchZoomListener implements MultiTouchZoomListener {
private PointF initialMultiTouchCenterPoint; private PointF initialMultiTouchCenterPoint;
private RotatedTileBox initialViewport; private RotatedTileBox initialViewport;
@ -765,12 +782,12 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
private static final float ANGLE_THRESHOLD = 15; private static final float ANGLE_THRESHOLD = 15;
@Override @Override
public void onZoomEnded(double relativeToStart, float angleRelative) { public void onZoomEnded(double relativeToStart, float angleRelative) {
// 1.5 works better even on dm.density=1 devices // 1.5 works better even on dm.density=1 devices
float dz = (float) (Math.log(relativeToStart) / Math.log(2)) * 1.5f; float dz = (float) (Math.log(relativeToStart) / Math.log(2)) * 1.5f;
setIntZoom(Math.round(dz) + initialViewport.getZoom()); setIntZoom(Math.round(dz) + initialViewport.getZoom());
if(Math.abs(angleRelative) < ANGLE_THRESHOLD * relativeToStart || if (Math.abs(angleRelative) < ANGLE_THRESHOLD * relativeToStart ||
Math.abs(angleRelative) < ANGLE_THRESHOLD / relativeToStart){ Math.abs(angleRelative) < ANGLE_THRESHOLD / relativeToStart) {
angleRelative = 0; angleRelative = 0;
} }
rotateToAnimate(initialViewport.getRotate() + angleRelative); rotateToAnimate(initialViewport.getRotate() + angleRelative);
@ -781,11 +798,11 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
} else { } else {
final LatLon p1 = initialViewport.getLatLonFromPixel(x1, y1); final LatLon p1 = initialViewport.getLatLonFromPixel(x1, y1);
final LatLon p2 = initialViewport.getLatLonFromPixel(x2, y2); final LatLon p2 = initialViewport.getLatLonFromPixel(x2, y2);
showMessage(OsmAndFormatter.getFormattedDistance((float)MapUtils.getDistance(p1.getLatitude(), p1.getLongitude(), p2.getLatitude(), p2.getLongitude()), application)); showMessage(OsmAndFormatter.getFormattedDistance((float) MapUtils.getDistance(p1.getLatitude(), p1.getLongitude(), p2.getLatitude(), p2.getLongitude()), application));
} }
} }
} }
@Override @Override
public void onGestureInit(float x1, float y1, float x2, float y2) { public void onGestureInit(float x1, float y1, float x2, float y2) {
this.x1 = x1; this.x1 = x1;
@ -810,21 +827,21 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
// keep only rotating // keep only rotating
dz = 0; dz = 0;
} }
if(Math.abs(relAngle) < ANGLE_THRESHOLD && !startRotating) { if (Math.abs(relAngle) < ANGLE_THRESHOLD && !startRotating) {
relAngle = 0; relAngle = 0;
} else { } else {
startRotating = true; startRotating = true;
} }
if(dz != 0 || relAngle != 0) { if (dz != 0 || relAngle != 0) {
changeZoomPosition((float) dz, relAngle); changeZoomPosition((float) dz, relAngle);
} }
} }
private void changeZoomPosition(float dz, float angle) { private void changeZoomPosition(float dz, float angle) {
final QuadPoint cp = initialViewport.getCenterPixelPoint(); final QuadPoint cp = initialViewport.getCenterPixelPoint();
float dx = cp.x - initialMultiTouchCenterPoint.x ; float dx = cp.x - initialMultiTouchCenterPoint.x;
float dy = cp.y - initialMultiTouchCenterPoint.y ; float dy = cp.y - initialMultiTouchCenterPoint.y;
final RotatedTileBox calc = initialViewport.copy(); final RotatedTileBox calc = initialViewport.copy();
calc.setLatLonCenter(initialCenterLatLon.getLatitude(), initialCenterLatLon.getLongitude()); calc.setLatLonCenter(initialCenterLatLon.getLatitude(), initialCenterLatLon.getLongitude());
@ -848,21 +865,22 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
@Override @Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
animatedDraggingThread.startDragging(velocityX, velocityY, animatedDraggingThread.startDragging(velocityX, velocityY,
e1.getX(), e1.getY(), e2.getX(), e2.getY(), true); e1.getX(), e1.getY(), e2.getX(), e2.getY(), true);
return true; return true;
} }
@Override @Override
public void onLongPress(MotionEvent e) { public void onLongPress(MotionEvent e) {
if (multiTouchSupport.isInZoomMode()) { if (multiTouchSupport.isInZoomMode() || afterTwoFingerTap) {
afterTwoFingerTap = false;
return; return;
} }
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("On long click event " + e.getX() + " " + e.getY()); //$NON-NLS-1$ //$NON-NLS-2$ log.debug("On long click event " + e.getX() + " " + e.getY()); //$NON-NLS-1$ //$NON-NLS-2$
} }
PointF point = new PointF(e.getX(), e.getY()); PointF point = new PointF(e.getX(), e.getY());
if ((accessibilityActions != null) && accessibilityActions.onLongClick(point, getCurrentRotatedTileBox() )) { if ((accessibilityActions != null) && accessibilityActions.onLongClick(point, getCurrentRotatedTileBox())) {
return; return;
} }
for (int i = layers.size() - 1; i >= 0; i--) { for (int i = layers.size() - 1; i >= 0; i--) {
@ -928,4 +946,5 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
} }
} }
} }