Girar MapView en Android

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é en la parte superior). 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, he tratado de sobrescribir el método dispatchDraw() así:

Nota:

-compass es un booleano que si es verdadero, rota la vista

-bearing es una variable flotante que tiene los grados que la vista debería 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.restre(); } 

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

Primero necesitará la clase interna de MapViewCompassDemo.java que se encuentra en: Android_SDK_ Tools \ add-ons \ addon-google_apis-google – # \ samples \ MapsDemo \ src \ com \ example \ android \ apis \ view \

 RotateView SmoothCanvas 

Extraiga la clase interna RotateView para RotateView.java y agregue SmoothCanvas como 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:

       

The MapActivity

  /** * Example activity on how to display a google map view rotation with compass * To make it work you need to add: * -  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: Rotar Google MapView con Compass Proyecto de ejemplo: https://www.dropbox.com/sh/c1encbc2lr63qd9/6C1C4hsrlT

De los documentos:

Despacho de vacío protegidoDibujo (canvas de canvas)

Llamado por sorteo para dibujar las vistas del niño. 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í que anular el envío no es bueno ya que la vista principal del mapa ya se ha dibujado

Una solución podría ser agregar MapView como elemento secundario de otra CustomView (una subclase de ViewGroup) y luego usar el método dispatchDraw de CustomView para dibujar MapView (ahora un elemento secundario) rotado. Entonces en xml harías algo como:

 < ?xml version="1.0" encoding="utf-8"?>      

Debería 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.restre(); } } 

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

 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)); }