2009-12-02 10 views
16

Estoy escribiendo una aplicación de Android donde una de las características es que el mapa rotará de acuerdo con la brújula (es decir, si el teléfono apunta hacia el este, el mapa estará orientado para que el lado este del mapa está arriba). Las respuestas anteriores que he encontrado sugirieron sobre escribir el método onDraw() en mapView, sin embargo, la API cambió el método a final, por lo que no se puede sobrescribir. Como resultado de ello he tratado de sobrescribir el método dispatchDraw() así:Rotar MapView en Android

Nota:

-Brújula es un valor lógico que si es cierto, girar la vista

-bearing es una variable de tipo float que tiene los grados que la visión debe girar

protected void dispatchDraw(Canvas canvas) { 
    canvas.save(); 
     if (compass) { 
      final float w = this.getWidth(); 
      final float h = this.getHeight(); 

      final float scaleFactor = (float)(Math.sqrt(h * h + w * w)/Math.min(w, h)); 

      final float centerX = w/2.0f; 
      final float centerY = h/2.0f; 

      canvas.rotate(bearing, centerX, centerY); 
      canvas.scale(scaleFactor, scaleFactor, centerX, centerY); 

     } 
     super.dispatchDraw(canvas); 
     canvas.restore(); 
} 
+0

¿Por qué necesita para anular onDraw, puede que no sólo animar la vista dentro de su actividad? – schwiz

+0

@Matthew: tiene usted la respuesta, si es así, por favor, dame la solución –

Respuesta

1

debe ser algo como esto:

@Override 
protected void dispatchDraw(Canvas canvas) { 
    canvas.save(Canvas.MATRIX_SAVE_FLAG); 
    if (compass) { 
     // rotate the canvas with the pivot on the center of the screen 
     canvas.rotate(-azimuth, getWidth() * 0.5f, getHeight() * 0.5f); 
     super.dispatchDraw(canvas); 
     canvas.restore(); 
    } 
} 
+0

¿Te funcionó? No funcionó para mí. –

3

A partir de los documentos:

protected void dispatchDraw (Lona)

Llamado por sorteo para dibujar las vistas secundarias. Esto puede ser anulado por las clases derivadas para ganar control justo antes de que sus hijos sean dibujados (pero después de que su propia vista haya sido dibujada).

Así anulando dispatchDraw hay buena como la vista del mapa principal ya se ha dibujado

Una solución podría ser la de añadir el MapView como un hijo de otro CustomView (una subclase de ViewGroup) y luego usar el método dispatchDraw de CustomView para dibujar MapView (ahora un elemento secundario) rotado. Así que en XML que haría algo como:

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

    <com.example.CustomView 
    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:apiKey="XXXXXXXXXXXXXXXXX"/> 

    </com.example.CustomView> 
</RelativeLayout> 
1

Tome un vistazo a los ejemplos MapsDemo en ANDROID_SDK\add-ons\addon-google_apis-google_inc_-7\samples\MapsDemo. Tiene demo de mapa de rotación.

8

Gracias a los phelcks y las respuestas de Nikita Koksharov, logro activar/desactivar la rotación de una vista de mapa según la brújula.

primer lugar se necesita la dos interno clase de MapViewCompassDemo.java encontrado en: Android_SDK_ Herramientas \ add-ons \ addon-google_apis-google - # \ samples \ MapsDemo \ src \ com \ ejemplo \ androide \ apis vista \

RotateView 
SmoothCanvas 

\ Extracto de la clase interna RotateView a RotateView.java y añadir SmoothCanvas como una clase interna de RotateView.java en lugar de MapViewCompassDemo.java

public class RotateView extends ViewGroup implements SensorListener { 
... 
    static final class SmoothCanvas extends Canvas { 
... 
    }//end SmoothCanvas 
}//end RotateView 

maplayout.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/map_layout_container" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:orientation="vertical" > 

<LinearLayout 
    android:id="@+id/rotating_view" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <com.google.android.maps.MapView 
     android:id="@+id/map_view" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:apiKey="##### YOUR MAP KEY HERE ######" 
     android:clickable="true" /> 
</LinearLayout> 

<ToggleButton 
    android:id="@+id/button_compass" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignParentBottom="true" 
    android:layout_centerHorizontal="true" 
    android:onClick="onClick" 
    android:textOff="compass off" 
    android:textOn="compass on" /> 

</RelativeLayout> 

El MapActivity

/** 
* Example activity on how to display a google map view rotation with compass 
* To make it work you need to add: 
* - <uses-library android:name="com.google.android.maps" /> in the manifest.xml file 
* - Your Android Maps API Key from https://developers.google.com/android/maps-api- signup 
* - Set the project build target to "Google APIs" 
* - Extract/Add the two inner classes RotateView and SmoothCanvas of MapViewCompassDemo.java found at: 
* ..\Android\Android SDK Tools\add-ons\addon-google_apis-google-#\samples\MapsDemo\src\com\example\android\apis\view\ 
* 
* @author hsigmond - touchboarder.com - 
* 
*/ 
public class MapViewRotationWithCompass extends MapActivity { 

private MapView mMapView; 
private MyLocationOverlay mMyLocationOverlay = null; 
private boolean mModeCompass = false; 
private SensorManager mSensorManager; 
private LinearLayout mRotateViewContainer; 
private RotateView mRotateView; 


@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.maplayout); 
    mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); 
    mRotateViewContainer = (LinearLayout) findViewById(R.id.rotating_view); 
    mRotateView = new RotateView(this); 

    // Sign Up for the Android Maps API at: 
    // https://developers.google.com/android/maps-api-signup 
    // Add the Android Maps API key to the MapView in the maplayout.xml file 
    mMapView = (MapView) findViewById(R.id.map_view); 
    mMyLocationOverlay = new MyLocationOverlay(this, mMapView);  

} 

@SuppressWarnings("deprecation") 
public void onClick(View v) { 

    switch (v.getId()) { 

    case R.id.button_compass: 
     if (mMyLocationOverlay.isCompassEnabled()) { 
      mSensorManager.unregisterListener(mRotateView); 
      mRotateView.removeAllViews(); 
      mRotateViewContainer.removeAllViews(); 
      mRotateViewContainer.addView(mMapView); 
      mMyLocationOverlay.disableCompass(); 
      mModeCompass = false; 
     } else { 
      mRotateViewContainer.removeAllViews(); 
      mRotateView.removeAllViews(); 
      mRotateView.addView(mMapView); 
      mRotateViewContainer.addView(mRotateView); 
      mMapView.setClickable(true); 
      mSensorManager.registerListener(mRotateView, 
        SensorManager.SENSOR_ORIENTATION, 
        SensorManager.SENSOR_DELAY_UI); 
      mMyLocationOverlay.enableCompass(); 
      mModeCompass = true; 
     } 
     break; 
    } 
} 

@SuppressWarnings("deprecation") 
@Override 
public void onResume() { 
    super.onResume(); 
    if (mModeCompass) { 
     mMyLocationOverlay.enableCompass(); 
     mSensorManager.registerListener(mRotateView, 
       SensorManager.SENSOR_ORIENTATION, 
       SensorManager.SENSOR_DELAY_UI); 
    } 
} 

@Override 
public void onPause() { 
    super.onPause(); 
    mMyLocationOverlay.disableCompass(); 
} 

@SuppressWarnings("deprecation") 
@Override 
protected void onStop() { 
    mSensorManager.unregisterListener(mRotateView); 
    super.onStop(); 
} 

@Override 
protected boolean isRouteDisplayed() { 
    return (false);// Don't display a route 
} 

} 

Actualización: Rotación de Google MapView con el Ejemplo Brújula Proyecto: https://www.dropbox.com/sh/c1encbc2lr63qd9/6C1C4hsrlT

+0

¿Me puede dar una demostración de trabajo completa? –

+0

Veré si tengo tiempo para hacer una demostración en funcionamiento. – TouchBoarder

+0

@Nirav Ranpara - He actualizado la respuesta con un proyecto de ejemplo en funcionamiento. – TouchBoarder

0
This answer applies to Google Maps api v2. 
It is possible by registering your application with Sensor Listener for Orientation and get the 
angle relative to true north inside onSensorChanged and update camera accordingly. 
Angle can be used for bearing. Following code can be used: 

Instead of using Sensor.TYPE_ORIENTATION try using getOrinetation api. Sensor.TYPE_ORIENTATION 
has been deprecated. 

@Override 
protected void onResume() { 
    // TODO Auto-generated method stub 
    super.onResume(); 
    if (sensorManager != null) 
     sensorManager.registerListener(this, 
       sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), 
       SensorManager.SENSOR_DELAY_GAME); 
} 

public void onSensorChanged(SensorEvent event) { 

    float degree = Math.round(event.values[0]); 

    Log.d(TAG, "Degree ---------- " + degree); 

    updateCamera(degree); 

} 

private void updateCamera(float bearing) { 
    CameraPosition oldPos = googleMap.getCameraPosition(); 

    CameraPosition pos = CameraPosition.builder(oldPos).bearing(bearing) 
      .build(); 

    googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(pos)); 

} 
Cuestiones relacionadas