6

I'm trying to implement a double-tap zoom like function in my MapView. The event always fires the first time, but never subsequent times. Below is my code. I have a feeling it has something to do with the map controller getting lost after the first time the event is fired.

import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;

public class mainmap extends MapActivity implements OnTouchListener{

    long lasttime = -1;
    MapController mapc;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        MapView mapView = (MapView) findViewById(R.id.mapview);
        mapView.setBuiltInZoomControls(true);
        mapc = mapView.getController();
        mapView.setOnTouchListener(this);       
    }

    @Override
    protected boolean isRouteDisplayed() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN){

            if(event.getEventTime()-lasttime<2000){
                mapc.zoomInFixing((int)event.getX(),(int)event.getY());             
            }
        }       
        lasttime=event.getEventTime();
        return true;
    }

  }

I have also tried editing the OnTouch method to cast the incoming View to a MapView, getting the controller while the event is fired. However, I get the same results where the first event is fired but not subsequent ones.

public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN){

            if(event.getEventTime()-lasttime<2000){
                ((MapView)v).getController().zoomInFixing((int)event.getX(), (int)event.getY());                
            }
        }       
        lasttime=event.getEventTime();
        return true;
    }

Being as basic as possible, I cut out all of the code in the OnTouch method and programmed it to simply display a small toast message.

public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN){

               Toast.makeText(this,"Down!",Toast.LENGTH_SHORT).show();

        }       

        return true;
}

This works as expected, displaying the Toast each time the MapView is touched.

I don't understand why the event will fire properly in this case but not in my previous implementation.

amandion
  • 347
  • 1
  • 3
  • 12

6 Answers6

13

If you are using this method "mapView.setBuiltInZoomControls(true);" then your touch is working at once .

Please remove that that line and check I am sure it will work..

In some case if you want BuiltInZoomControls then you can you OnTouch method of Overlay like as below..

public class MapOverlay extends Overlay {

    public MapOverlay(Context ctx) {super(ctx);}

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

    @Override
    public boolean onTouchEvent(MotionEvent e, MapView mapView) {
        //Write yout touch code here..
        return false;
    }
}
Niranj Patel
  • 32,980
  • 10
  • 97
  • 133
  • It is true, but why touch event called once? – Nik May 24 '12 at 12:43
  • I didn't waste my time on it, so I don't know about it. I think no need builtInZoom Button bcz map already support multi-touch zoom & you can also add your custom button for zoom In/Out.. – Niranj Patel May 24 '12 at 13:00
  • How in the Overlay class related with this problem - the mapView and the zoom controls? – User Nov 14 '12 at 13:37
  • To add a bit more to CapDroid's answer, I created an instance of MapOverly as shown above, and added it to the overlays of the map. And it works as advertised. :) – strangeluck Dec 10 '13 at 19:41
2

Subclass MapView and override dispatchTouchEvent like below and use the subclass instead.

public class MyMap extends MapView{
@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
         if (mOnMovedListener!= null) {
                mOnMovedListener.onMove(ev);
            }
            return super.dispatchTouchEvent(ev);
        }
    private OnMovedListener mOnMovedListener;

    public void setOnMovedListener(OnMovedListener mOnMovedListener) {
        this.mOnMovedListener= mOnMovedListener;
    }
}

register for listener like any other!

stack_ved
  • 721
  • 3
  • 11
1

I was having the same problem - I couldn't drag and scroll the map because it was receiving only ACTION_DOWN events. It can be solved by adding android:clickable="true" to the MapView or by calling mapView.setClickable(true).

Pratik
  • 30,639
  • 18
  • 84
  • 159
fhucho
  • 34,062
  • 40
  • 136
  • 186
0

How about using a GestureDetector.OnDoubleTapListener instead of OnTouchListener?

Paul Burke
  • 25,496
  • 9
  • 66
  • 62
  • Thanks for your suggestion. I will try to implement an OnDoubleTapListener to handle this functionality instead. I'm still confused though. I understand OnDoubleTapListener is probably the best way to handle this, but the code I posted in theory should work, right? – amandion Sep 08 '10 at 14:05
0

you should at least put

lasttime=event.getEventTime();

under the

if (event.getAction() == MotionEvent.ACTION_DOWN) brakes 

while onTouch detect ACTION_UP event of your click. So any time you make a click it is called 2 times

Pratik
  • 30,639
  • 18
  • 84
  • 159
Maxim
  • 2,996
  • 17
  • 19
-1

Implement the Touch event on the map view instead. That will work!!

    // The onTouch event of the Map itself does not fire!
    // We must implement it on the mapView!!!
    mapView.setOnTouchListener(new OnTouchListener()
    {
        public boolean onTouch(View v, MotionEvent event) 
        {
            // Your code and remember to return true!                

            return (true);
        }
    });