3

I simply want a mapview to recognize a click, in order to call another activity.

Until now, i tried the regular "onClick",that always worked for me in regular Views, followed by overriding "onTouchEvent" and last but not least using an onClickListener.

I out all three ways into the following code. Any help is highly appreciated.

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

public class HelloMapView extends MapActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
     final MapView map;
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        map = (MapView) findViewById(R.id.mapview);

        map.setOnClickListener(new MapView.OnClickListener() {
         public void onClick(View v){
          System.out.println("I listened!");
         }  
        });
    }
    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent arg0) {

     System.out.println("onTouchEvent happened!");        
        super.onTouchEvent(arg0);

        return super.onTouchEvent(arg0);
        }

    public void onClick(){
     System.out.println("onClick entered!");
    }    
}
Ben
  • 33
  • 1
  • 3

4 Answers4

10

I know it's pretty old question, but:

mMapView.getMap().setOnMapClickListener(new OnMapClickListener()
                {
                    @Override
                    public void onMapClick(LatLng arg0)
                    {
                        android.util.Log.i("onMapClick", "Horray!");
                    }
                });

Will do the trick.

Givi
  • 3,283
  • 4
  • 20
  • 23
6

Add an Overlay in your map view and handle the OnTouchEvent. Try something like this:

public class MyMapActivity extends MapActivity {

class MapOverlay extends com.google.android.maps.Overlay
{       
    @Override
    public boolean onTouchEvent(MotionEvent e, MapView mapView) 
    {   
        if (e.getAction() == MotionEvent.ACTION_UP) {                
            GeoPoint p = mapView.getProjection().fromPixels(
                (int) e.getX(),
                (int) e.getY());
            MyMapActivity this.startActivityForResult(intent, requestCode);
        }                            
        return false;
    }        
}

      // MyMapActivity methods
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mapView = (MapView) findViewById(R.id.mapview);

        MapOverlay mapOverlay = new MapOverlay();
        List<Overlay> listOfOverlays = mapView.getOverlays();
        listOfOverlays.clear();
        listOfOverlays.add(mapOverlay);
  }
}
Rune
  • 698
  • 1
  • 7
  • 22
kgiannakakis
  • 103,016
  • 27
  • 158
  • 194
  • The Problem with an Overlay is, that i can't call "StartActivityForResult" out of it, as far as i know. So even if i do the whole "where-did-the-user-click-thing" inside an overlay, i need to trigger my Map Activity somehow, in order to call "StartActivityForResult", using the data received from the overlay – Ben Dec 22 '10 at 21:43
  • Overlays are usually implemented as inner classes. So it will be possible to call Activity methods from them. See my edited answer. – kgiannakakis Dec 23 '10 at 08:46
  • Ah, I see. I didnt know that fact about Overlays. Thanks a lot, i will try that! – Ben Dec 23 '10 at 09:02
  • 3
    Im sorry to dig up such an old post, but the way suggested above will start the activity even if the user just drags the map (and releases). Is there any way we can detect just a tap and not a drag and release? – Urban Mar 21 '12 at 20:01
0

I used something similar to kgiannakakis' answer, with an inner MapOverlay class, but I overloaded the OnTap() method to provide an Exit_Dialog to close down the activity. This implementation still allows for zoom and drag control on the MapView without affecting the Overlay control. But you must use mMapView.getContext() in the AlertDialog.Builder construction. See code:

public class TripDataMapActivity extends MapActivity { 

    ....
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mapview_activity);

        // Set result CANCELED in case the user backs out
        setResult(Activity.RESULT_CANCELED);

        mMapView = (MapView)findViewById(R.id.mapview);
        mMapView.setBuiltInZoomControls(true);

        mMapCntrl = mMapView.getController();
        mMapCntrl.setZoom(14);  // World View is Zoom 1            

        // Set-up Drawable Overlays
        mMapOverlays = mMapView.getOverlays();
        mMapOverlays.clear();
        mDrawable = this.getResources().getDrawable(R.drawable.direction_arrow);
        mItemizedOverlay = new MyItemizedOverlays(mDrawable);
        updateMapView();
    }
    .....

    protected void updateMapView() { 
        // Convert Location into GeoPoint.
        int lat = (int)(locatn.getLatitude() * 1E6);  
        int lng = (int)(locatn.getLongitude() * 1E6); 
        GeoPoint point = new GeoPoint(lat, lng);
        OverlayItem overlayitem = new OverlayItem(point, "someTitle!", "someSnippet!");
        mMapCntrl.setCenter(point); 

        mItemizedOverlay.addOverlay(overlayitem);
        mMapOverlays.add(mItemizedOverlay);
        mMapView.invalidate();
    }
    ....
    // Inner Class Implementation 
    class MyItemizedOverlays extends ItemizedOverlay<OverlayItem> {

    private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>(); 

    public MyItemizedOverlays(Drawable defaultMarker) {
        super(boundCenterBottom(defaultMarker));
    }

    @Override
    protected OverlayItem createItem(int ith) { return mOverlays.get(ith); }

    @Override
    public int size() { return mOverlays.size(); }

    public void addOverlay(OverlayItem overlay) {
    mOverlays.add(overlay);
    populate();  // will call createItem(int) above 
    }

    @Override
    protected boolean onTap(int index) {

    // EXIT Dialog
    AlertDialog.Builder exitDialog = 
            new AlertDialog.Builder(mMapView.getContext());
        exitDialog.setMessage("Are you sure you want to Exit?")
                          .setCancelable(false)
        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {

                public void onClick(DialogInterface dialog, int id) {

            Intent intent = new Intent();
            //intent.putExtra(EXTRA_DEVICE_ADDRESS, address);
            // Set result and finish this Activity
            setResult(Activity.RESULT_OK, intent);

            TripDataMapActivity.this.finish();
            }
        }).setNegativeButton("No", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
               }
        });
        exitDialog.show();

    return true;
    }
    // End of Inner Class
}

}     
Eddie Moxey
  • 91
  • 1
  • 1
  • 6
0

I would prefer to override the onTap method.

class MapOverlay extends Overlay
{       
  @Override
    public boolean onTap(GeoPoint p, MapView mapView) {
        //DO YOUR STUFF
        return super.onTap(p, mapView);
    }
}

In the onTouch event you have to define a tab by your self by waiting for MotionEvent.ACTION_DOWN and MotionEvent.ACTION_UP. And you have to filter out the MotionEvent.ACTION_MOVE to avoid doing your stuff while the user just moves the map.

Filtering the move event can lead to problems when developing for older Android Versions as well. As I tested the move event will be thrown in my Android 2.3.3 Phone even when I didn't moved the map. So I couldn't distinguish between a normal click (down and up) and a move (down, move and up)

salcosand
  • 2,022
  • 4
  • 24
  • 27