2010-01-06 21 views
37

Estamos construyendo una aplicación que utiliza la API de Google Maps para Android.En caso de zoom para google maps en android

tengo mi MapController y MapView, y puedo activar el incorporado en los controles de zoom usando:

mapView.setBuiltInZoomControls(true); 

Ahora me gustaría conseguir un evento cuando el usuario realmente hace zoom en el mapa, ¿cómo voy ¿sobre eso? No puedo encontrar ningún evento o evento general en el que pueda detectar un cambio en el nivel de zoom.

actualización

The mapView.getZoomControls() is deprecated. Y la documentación sugiere utilizar mapView.setBuiltInZoomControls (bool) en su lugar. Esto está bien, pero simplemente no puedo entender cómo actuar sobre los eventos desde los controles de zoom integrados.

+3

Intenté implementar el evento onUserInteraction, para el mismo propósito, pero todavía tengo un problema. Estoy visualizando una imagen que necesita ser escalada de acuerdo con el nivel de zoom, así que obviamente quiero llamar a su método redraw() cuando un usuario amplía. Mi problema es que onUserInteraction se invoca cuando el usuario hace clic en el botón de zoom, por lo que zoomLevel no se actualiza aún y solo en la siguiente interacción (click, span, whatever) el zoomLevel se actualiza. Entonces, mi imagen se actualiza solo después de una interacción después del zoom real. ¿Algunas ideas? – Itsik

+1

Esta pregunta y respuesta se refieren a API v1, agregué una nueva respuesta a continuación para saber quién está usando [Google Maps Android API v2] (https://developers.google.Gracias por la respuesta, com/maps/documentation/android /) – tarmelop

Respuesta

37

Con la versión 2 del API de Google Maps para Android se puede utilizar un GoogleMap.OnCameraChangeListener así:

mMap.setOnCameraChangeListener(new OnCameraChangeListener() { 

    private float currentZoom = -1; 

    @Override 
    public void onCameraChange(CameraPosition pos) { 
     if (pos.zoom != currentZoom){ 
      currentZoom = pos.zoom; 
      // do you action here 
     } 
    } 
}); 
+3

'setOnCameraChangeListener()' ahora está en desuso –

4

El android API sugiere que utilice ZoomControls que tiene una setOnZoomInClickListener()

Para agregar estos controles de zoom que usted haría:

ZoomControls mZoom = (ZoomControls) mapView.getZoomControls(); 

y luego añadir mZoom a su disposición.

+0

MapView.getZoomControls() está en desuso, con la sugerencia de utilizar el método MapView.setBuiltInZoomControls (boolean). Pero no puedo encontrar ningún lugar para obtener ningún evento de estos controles de zoom incorporados. Ref: http://code.google.com/android/add-ons/google-apis/reference/com/google/android/maps/MapView.html#getZoomControls(). –

+0

Ya veo. Bueno, parece que hay un mapView.getZoomButtonsController() no documentado que podría usar, descrito en http://code.google.com/p/android/issues/detail?id=3348, de lo contrario, tendrá que usar el mapview.onkeydown y prueba para el zoom. – JasonOfEarth

+0

Obtuve lo que quería usando el evento onUserInteraction y probando manualmente un cambio en el nivel de zoom. Funciona muy bien con un mensaje de brindis notificando al usuario de la necesidad de hacer zoom para ver mi superposición. –

5

Como dijo el OP, use el onUserInteractionEvent y haga la prueba usted mismo.

+3

'onUserInteractionEvent()' se llama * antes * el nivel de zoom cambia. Esto significa que con cada evento de zoom, la aplicación que monitorea el zoom se está ejecutando un evento detrás. –

+0

@Paul: Hola. Originalmente no consideré esto, pero parece que tienes razón, las tostadas que muestro siempre son una, incluso las que están atrás. –

+1

Puede crear una instancia de 'Handler' y comprobar periódicamente los cambios de nivel de zoom a través de algo como' postDelayed (new Runnable() {...}, 500) ', pero realmente no me gusta esa solución. –

4

Usted puede utilizar

ZoomButtonsController zoomButton = mapView.getZoomButtonsController(); 
zoomButton.setOnZoomListener(listener); 

creo que sirve

+2

Esto responde específicamente a la pregunta del OP, pero solo plantea un evento para los eventos de zoom a través de los botones del zoom. El pellizco, por ejemplo, no llama a la devolución de llamada del oyente. –

2

T puede tener zoom CControl como este.

Aquí adjunto el código de cómo se puede implementar el control de zoom.

1 >> El archivo XML debería ser así.

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 

    <com.google.android.maps.MapView 
     android:id="@+id/mapView" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:enabled="true" 
     android:clickable="true" 
     android:apiKey="0l4sCTTyRmXTNo7k8DREHvEaLar2UmHGwnhZVHQ" 
     /> 

    <LinearLayout android:id="@+id/zoom" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_centerHorizontal="true" 
     /> 

</RelativeLayout> 

2 >> Actividad principal dentro del método oncreate haz lo siguiente. aquí se están inflando su visión con MAPview

mapView = (MapView) findViewById(R.id.mapView); 
     LinearLayout zoomLayout = (LinearLayout)findViewById(R.id.zoom); 
     View zoomView = mapView.getZoomControls(); 

     zoomLayout.addView(zoomView, 
      new LinearLayout.LayoutParams(
       LayoutParams.WRAP_CONTENT, 
       LayoutParams.WRAP_CONTENT)); 
     mapView.displayZoomControls(true); 

.................................. ......................... Así es como puede usar el control de zoom incorporado de la API ...

Puede tener su propio código personalizado a aplicar zoom in y zoom out así ...

public boolean onKeyDown(int keyCode, KeyEvent event) 
{ 
    MapController mc = mapView.getController(); 
    switch (keyCode) 
    { 
     case KeyEvent.KEYCODE_3: 
      mc.zoomIn(); 
      break; 
     case KeyEvent.KEYCODE_1: 
      mc.zoomOut(); 
      break; 
    } 
    return super.onKeyDown(keyCode, event); 
}  

..Esta es como he implementado ...

Thanks..Rakesh

25

Puede implementar su propio "sondeo" básico del valor del zoom para detectar cuándo se ha cambiado el zoom utilizando el android Handler.

Utilizando el siguiente código para su evento ejecutable. Aquí es donde debe hacerse su procesamiento.

private Handler handler = new Handler(); 

public static final int zoomCheckingDelay = 500; // in ms 

private Runnable zoomChecker = new Runnable() 
{ 
    public void run() 
    { 
     checkMapIcons(); 

     handler.removeCallbacks(zoomChecker); // remove the old callback 
     handler.postDelayed(zoomChecker, zoomCheckingDelay); // register a new one 
    } 
}; 

inicio un evento de devolución de llamada usando

protected void onResume() 
{ 
    super.onResume(); 
    handler.postDelayed(zoomChecker, zoomCheckingDelay); 
} 

y parada que cuando estás dejando la actividad usando

protected void onPause() 
{ 
    super.onPause(); 
    handler.removeCallbacks(zoomChecker); // stop the map from updating 
} 

artículo esto se basa en puede ser encontrado here si quieres una más larga escribir.

+1

He otorgado el premio a esta respuesta, porque esta es la forma más simple de determinar si el mapa se ha movido o se ha ampliado. –

1

Utilicé una mezcla de las anteriores. Descubrí que usar el temporizador para iniciar un hilo cada medio segundo hace que el mapa sea realmente jenky. Probablemente porque estaba usando un par de declaraciones If cada vez. Así que comencé el hilo en una demora de 500ms desde onUserInteraction. Esto da tiempo suficiente para que zoomLevel se actualice antes de que el hilo comience a ejecutarse, obteniendo así el nivel de zoom correcto sin ejecutar un hilo cada 500 ms.

public void onUserInteraction() { 
    handler.postDelayed(zoomChecker, zoomCheckingDelay); 
} 
3

Creo que podría haber otra respuesta a esta pregunta. El método de dibujo de la clase de superposición se llama después de cualquier zoom y creo que se llama después de que cambia el nivel de zoom. ¿No podrías diseñar tu aplicación para aprovechar esto? Incluso podrías usar una superposición ficticia solo para detectar esto si quisieras. ¿No sería esto más eficiente que usar un ejecutable con un retraso?

@Override 
public boolean draw (Canvas canvas, MapView mapView, boolean shadow, long when) { 
    int zoomLevel = mapView.getZoomLevel(); 
    // do what you want with the zoom level 
    return super.draw(canvas, mapView, shadow, when); 
} 
4

Aquí hay una solución limpia. Simplemente agregue esta clase privada TouchOverlay a su actividad y un método llamado onZoom (que es llamado por esta clase interna).

Tenga en cuenta que tendrá que agregar esta TouchOverlay a su mapView, p.

mapView.getOverlays().add(new TouchOverlay()); 

Realiza un seguimiento del nivel de acercamiento cada vez que el usuario toca el mapa, p. para hacer doble toque o acercar el zoom y luego dispara el método onZoom (con el nivel de zoom) si el nivel de zoom cambia.

private class TouchOverlay extends com.google.android.maps.Overlay { 
      int lastZoomLevel = -1; 

      @Override 
      public boolean onTouchEvent(MotionEvent event, MapView mapview) { 
       if (event.getAction() == 1) { 
        if (lastZoomLevel == -1) 
         lastZoomLevel = mapView.getZoomLevel(); 

        if (mapView.getZoomLevel() != lastZoomLevel) { 
         onZoom(mapView.getZoomLevel()); 
         lastZoomLevel = mapView.getZoomLevel(); 
        } 
       } 
       return false; 
      } 
     } 

     public void onZoom(int level) { 
      reloadMapData(); //act on zoom level change event here 
     } 
+0

Con su solución, ¡pude capturar fácilmente los cambios de zoom! Thx –

+0

Solución brillante, sin embargo, no estaba detectando el primer cambio en el zoom. Sin embargo, eliminar la primera instrucción if para -1 solucionó esto. – Aelexe

2

Para pre-V2.0, hice una clase que se extiende MapView que alerta a un oyente con eventos cuando la región del mapa comienza a cambiar (onRegionBeginChange) y deja de cambiar (onRegionEndChange).

import android.content.Context; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 

import com.google.android.maps.GeoPoint; 
import com.google.android.maps.MapView; 

public class ExMapView extends MapView { 
    private static final String TAG = ExMapView.class.getSimpleName(); 
    private static final int DURATION_DEFAULT = 700; 

    private OnRegionChangedListener onRegionChangedListener; 
    private GeoPoint previousMapCenter; 
    private int previousZoomLevel; 
    private int changeDuration; // This is the duration between when the user stops moving the map around and when the onRegionEndChange event fires. 
    private boolean isTouched = false; 
    private boolean regionChanging = false; 

    private Runnable onRegionEndChangeTask = new Runnable() { 
     public void run() { 
      regionChanging = false; 
      previousMapCenter = getMapCenter(); 
      previousZoomLevel = getZoomLevel(); 
      if (onRegionChangedListener != null) { 
       onRegionChangedListener.onRegionEndChange(ExMapView.this, previousMapCenter, previousZoomLevel); 
      } 
     } 
    }; 

    public ExMapView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    public ExMapView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(); 
    } 

    public ExMapView(Context context, String apiKey) { 
     super(context, apiKey); 
     init(); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     isTouched = event.getAction() != MotionEvent.ACTION_UP; 
     return super.onTouchEvent(event); 
    } 

    @Override 
    public void computeScroll() { 
     super.computeScroll(); 

     // If the map region is still changing (user is still scrolling or zooming), reset timer for onRegionEndChange. 
     if ((!isTouched && !getMapCenter().equals(previousMapCenter)) || (previousZoomLevel != getZoomLevel())) { 

      // If the region has just begun changing, fire off onRegionBeginChange event. 
      if (!regionChanging) { 
       regionChanging = true; 
       if (onRegionChangedListener != null) { 
        onRegionChangedListener.onRegionBeginChange(this, previousMapCenter, previousZoomLevel); 
       } 
      } 

      // Reset timer for onRegionEndChange. 
      removeCallbacks(onRegionEndChangeTask); 
      postDelayed(onRegionEndChangeTask, changeDuration); 
     } 
    } 

    private void init() { 
     changeDuration = DURATION_DEFAULT; 
     previousMapCenter = getMapCenter(); 
     previousZoomLevel = getZoomLevel(); 
    } 

    public void setOnRegionChangedListener(OnRegionChangedListener listener) { 
     onRegionChangedListener = listener; 
    } 

    public void setChangeDuration(int duration) { 
     changeDuration = duration; 
    } 

    public interface OnRegionChangedListener { 
     public abstract void onRegionBeginChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel); 
     public abstract void onRegionEndChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel); 
    } 
} 
Cuestiones relacionadas