Rotar MapView en Android
google-maps rotation (5)
De los documentos:
void protegido dispatchDraw (lienzo de lona)
Llamado por sorteo para dibujar las vistas del niño. Esto puede ser anulado por clases derivadas para ganar control justo antes de que se dibujen sus hijos (pero después de que se haya dibujado su propia vista).
Así que sobrescribir dispatchDraw no es bueno ya que la vista del mapa principal ya ha sido dibujada
Una solución podría ser agregar MapView como un elemento secundario de otra CustomView (una subclase de ViewGroup) y luego usar el método dispatchDraw de CustomView para dibujar el MapView (ahora un elemento secundario) girado. Así que en xml harías 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>
Estoy escribiendo una aplicación para Android donde una de las características es que el mapa girará de acuerdo con la brújula (es decir, si el teléfono apunta al este, el mapa estará orientado de modo que el lado este del mapa esté en la parte superior). Las respuestas anteriores que he encontrado sugeridas sobre la escritura del 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()
manera:
Nota:
-compass es un booleano que, si es verdadero, rota la vista
La orientación es una variable flotante que tiene los grados que la vista debe rotar.
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();
}
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.restore();
}
}
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
. Cuenta con mapa de rotación demo.
Gracias a las respuestas de pheelicks y Nikita Koksharov, logro activar / desactivar la rotación de una vista de mapa según la brújula.
Primero necesitará las dos clases internas de MapViewCompassDemo.java que se encuentran 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 a RotateView.java y agregue 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 Compass Ejemplo de proyecto: https://www.dropbox.com/sh/c1encbc2lr63qd9/6C1C4hsrlT
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));
}