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
How to Convert Rgb Color to Int in Java
Xmpp with Java Asmack Library Supporting X-Facebook-Platform
Why Can't I Use Resources.Getsystem() Without a Runtime Error
Reducing Android App (Apk) Size
Portrait for Phone, Landscape for Tablet (Android-Layout)
Converting Epoch Time to Date String
Java Apns Certificate Error with "Derinputstream.Getlength(): Lengthtag=109, Too Big."
Hbase Client Connectionloss for /Hbase Error
Spark Error - Unsupported Class File Major Version
Reading Properties File in Java
How to Resume Android Activity Programmatically from Background
Networksecurityconfig: No Network Security Config Specified -- Android 7.0 Error
Reusing Views in Android Listview with 2 Different Layouts
R.Raw.Anything Cannot Be Resolved