Double Tap: Zoom on Android Mapview

Double tap: zoom on Android MapView?

Implement GestureListener to receive doubleTap events.

see: Fling gesture detection on grid layout

Double Tap to Zoom Feature for Map Fragment

I tried all possible solutions from here and here in which they have given some other ways to handle the double tap by the help of the touch event. But unfortunately nothing worked for me.

So I ended with the predefined onMapClickListener() which calls on a single click of the map. I pasted my solution below:

 getMap().setOnMapClickListener(new GoogleMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
getMap().animateCamera(CameraUpdateFactory.zoomIn());
}
});

Anyways thanks Karan Mer for the help.

How to detect onDoubleTap zoom in googleMap android

You can modify public boolean dispatchTouchEvent(MotionEvent event) in that answer for your previous question for detect double taps on delays between first and second taps, for example that way:

public class TouchableWrapper extends FrameLayout {

private GoogleMap mGoogleMap = null;
private long mLastTouchTime = -1; // time of first tap

public TouchableWrapper(Context context) {
super(context);
}

public void setGoogleMap(GoogleMap googleMap) {
mGoogleMap = googleMap;
}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {

switch (event.getAction() & MotionEvent.ACTION_MASK) {

case MotionEvent.ACTION_DOWN:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(true);

long thisTime = System.currentTimeMillis(); // time of second tap tap
if (thisTime - mLastTouchTime < ViewConfiguration.getDoubleTapTimeout()) {
// double tap detected! do you magic here:
if (mGoogleMap != null) {
LatLng zoomCenter = mGoogleMap.getProjection().fromScreenLocation(new Point((int)event.getX(), (int)event.getY()));
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(zoomCenter, currentZoom + 1));
}
mLastTouchTime = -1;
} else {
mLastTouchTime = thisTime;
mGoogleMap.getUiSettings().setZoomGesturesEnabled(true);
}

break;

case MotionEvent.ACTION_POINTER_DOWN:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(false);
break;

case MotionEvent.ACTION_POINTER_UP:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(true);
break;

case MotionEvent.ACTION_UP:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(true);
break;
}

return super.dispatchTouchEvent(event);
}
}

UPDATE:

If you use MapView instead of MapFregment - better way is to create custom view, which extends MapView implements OnMapReadyCallback (it's neccessary for get GoogleMap object), and overrides dispatchTouchEvent() (for double tap detection). Something like that:

public class EnhanchedMapView extends MapView implements OnMapReadyCallback {
private long mLastTouchTime = -1;

private OnMapReadyCallback mMapReadyCallback;
private GoogleMap mGoogleMap;
private Marker mMarker;
private Paint mPaintArrow;

public EnhanchedMapView(@NonNull Context context) {
super(context);
init();
}

public EnhanchedMapView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}

public EnhanchedMapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

public EnhanchedMapView(@NonNull Context context, @Nullable GoogleMapOptions options) {
super(context, options);
init();
}

private void init() {
}

@Override
public void getMapAsync(OnMapReadyCallback callback) {
mMapReadyCallback = callback;
super.getMapAsync(this);
}

@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {

switch (event.getAction() & MotionEvent.ACTION_MASK) {

case MotionEvent.ACTION_DOWN:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(true);

long thisTime = System.currentTimeMillis();
if (thisTime - mLastTouchTime < ViewConfiguration.getDoubleTapTimeout()) {

if (mGoogleMap != null) {
LatLng zoomCenter = mGoogleMap.getProjection().fromScreenLocation(new Point((int) event.getX(), (int) event.getY()));
float currentZoom = mGoogleMap.getCameraPosition().zoom;
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(zoomCenter, currentZoom + 1));
}
mLastTouchTime = -1;
} else {
mLastTouchTime = thisTime;
mGoogleMap.getUiSettings().setZoomGesturesEnabled(true);
}

break;

case MotionEvent.ACTION_POINTER_DOWN:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(false);
break;

case MotionEvent.ACTION_POINTER_UP:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(true);
break;

case MotionEvent.ACTION_UP:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(true);
break;
}

return super.dispatchTouchEvent(event);
}
}

UPDATE #2:

Activity layout for activity (MainActivity) that case can be like:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="{YOUR_PACKAGE}.MainActivity">

<{YOUR_PACKAGE}.EnhanchedMapView
android:id="@+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>

</RelativeLayout>

And only changes in MainActivity source code is:

...
private EnhanchedMapView mMapView;
...

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

...
mMapView = (EnhanchedMapView) findViewById(R.id.mapview);
...
}

UPDATE #3:

public class EnhanchedMapView extends MapView implements OnMapReadyCallback {
private long mLastTouchTime = -1;

private OnMapReadyCallback mMapReadyCallback;
private GoogleMap mGoogleMap;

private LatLng mZoomCenter;

public EnhanchedMapView(@NonNull Context context) {
super(context);
init();
}

public EnhanchedMapView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}

public EnhanchedMapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

public EnhanchedMapView(@NonNull Context context, @Nullable GoogleMapOptions options) {
super(context, options);
init();
}

private void init() {
}

@Override
public void getMapAsync(OnMapReadyCallback callback) {
mMapReadyCallback = callback;
super.getMapAsync(this);
}

@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {

switch (event.getAction() & MotionEvent.ACTION_MASK) {

case MotionEvent.ACTION_DOWN:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(true);
mGoogleMap.getUiSettings().setZoomGesturesEnabled(false);

mZoomCenter = mGoogleMap.getCameraPosition().target;

long thisTime = System.currentTimeMillis();
if (thisTime - mLastTouchTime < ViewConfiguration.getDoubleTapTimeout()) {

if (mGoogleMap != null) {
LatLng zoomCenter = mGoogleMap.getProjection().fromScreenLocation(new Point((int) event.getX(), (int) event.getY()));
float currentZoom = mGoogleMap.getCameraPosition().zoom;
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mZoomCenter, currentZoom + 1));
}
mLastTouchTime = -1;
} else {
mLastTouchTime = thisTime;
mGoogleMap.getUiSettings().setZoomGesturesEnabled(true);
}

break;

case MotionEvent.ACTION_POINTER_DOWN:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(false);
break;

case MotionEvent.ACTION_POINTER_UP:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(true);
break;

case MotionEvent.ACTION_UP:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(true);
break;
}

return super.dispatchTouchEvent(event);
}
}

how can i implement my own double-tap in mapview?

I had a similar requirement with the Osmdroid MapView, in that I didn't want it to do the 'centre on the double tapped location and zoom in' default functionality. I wanted it to pop up a Toast. In my case I had an overlay on top of the MapView, so I just had the overlay consume the double tap in its onDoubleTap method. For your purposes you could just add an overlay which draws nothing but has its own double tap functionality.

So at the end of your onCreate, you could add the overlay. This little app seems to demonstrate what you want - (you'll need to add conditional code for checking zoom level and other tinkering):

public class OsmdroidDemoMap extends Activity {

private MapView mMapView;
private MapController mMapController;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.osm_main);
mMapView = (MapView) findViewById(R.id.mapview);
mMapView.setTileSource(TileSourceFactory.MAPNIK);
mMapView.setBuiltInZoomControls(true);
mMapController = mMapView.getController();
mMapController.setZoom(13);
GeoPoint gPt = new GeoPoint(51500000, -150000);
mMapController.setCenter(gPt);
DummyOverlay dumOverlay = new DummyOverlay(this);
List<Overlay> listOfOverlays = mMapView.getOverlays();
listOfOverlays.clear();
listOfOverlays.add(dumOverlay);
}

public class DummyOverlay extends org.osmdroid.views.overlay.Overlay {

public DummyOverlay(Context ctx) {
super(ctx); // TODO Auto-generated constructor stub
}

@Override
protected void draw(Canvas c, MapView osmv, boolean shadow) {}

@Override
public boolean onDoubleTap(MotionEvent e, MapView mapView) {
// This stops the 'jump to, and zoom in' of the default behaviour
int zoomLevel = mMapView.getZoomLevel();
mMapController.setZoom(zoomLevel + 3);
return true;// This stops the double tap being passed on to the mapview
}
}

double click/tap map zoom (Android)

Since you want a copy-paste answer, look here.

EDIT:

In my public class MainMap extends MapActivity I have a field called private MyMapView mv;

I then made a class which extends MapView like this:
public class MyMapView extends MapView.

So you just make a new class which extends MapView, copy-paste the code you found in the link in there, and use your new class in your Activity which extends MapActivity.

Osmdroid disable double tap zoom

I set my own onTouchListener with my own gestureDetector to intercept the onDoubleTap. This effectivly stops the mapview doing it's standard doubletap.

some code snippets.

mGestureDetector = new GestureDetector(this, this);
mMapView.setOnTouchListener(mOnTouchListener);

public OnTouchListener mOnTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mGestureDetector.onTouchEvent(event))
return true;
else
return false;
}
};

@Override
public boolean onDoubleTap(MotionEvent arg0) {
Log.v(TAG, "onDoubleTap");
return true;
}


Related Topics



Leave a reply



Submit