2009-12-02 17 views
16

Sto scrivendo un'app per Android in cui una delle caratteristiche è che la mappa ruoterà secondo la bussola (cioè se il telefono punta verso est, la mappa sarà orientata in modo che il lato est della mappa è in cima). Le risposte precedenti che ho trovato suggeriscono sulla scrittura del metodo onDraw() in mapView, tuttavia, l'API ha cambiato il metodo in final in modo che non possa essere sovrascritto. Come risultato ho cercato di sovrascrivere il metodo dispatchDraw() modo:Ruota MapView in Android

Nota:

-compass è un booleano che, se vero, ruotare la vista

-bearing è una variabile float che ha gradi che la vista deve ruotare

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

perché avete bisogno di ignorare OnDraw, può non solo animare la vista all'interno della tua attività? – schwiz

+0

@Matthew: hai una risposta, se sì per favore dammi una soluzione –

risposta

1

dovrebbe essere qualcosa di simile:

@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

Ha funzionato per te? Non ha funzionato per me. –

3

Dalla documentazione:

protected void dispatchDraw (Tela)

Chiamato dal sorteggio per disegnare il punto di vista del bambino. Questo può essere sovrascritto dalle classi derivate per ottenere il controllo prima che i suoi figli vengano disegnati (ma dopo che è stata disegnata la propria vista).

Quindi override dispatchDraw non è buono come la vista della mappa principale è già stato disegnato

Una soluzione potrebbe essere quella di aggiungere il MapView come figlio di un altro CustomView (una sotto-classe di ViewGroup) e quindi utilizzare il metodo dispatchDraw di CustomView per disegnare il MapView (ora un bambino) ruotato. Quindi, in xml faresti qualcosa di simile:

<?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

Date un'occhiata a esempi MapsDemo in ANDROID_SDK\add-ons\addon-google_apis-google_inc_-7\samples\MapsDemo. Ha demo della mappa di rotazione.

8

Grazie a pheelicks e Nikita Koksharov risponde, riesco ad attivare/disattivare la rotazione di una vista mappa in base alla bussola.

primo luogo è necessario il due interna classe di MapViewCompassDemo.java trovato in: Android_SDK_ Tools \ add-ons \ addon-google_apis-google - # \ campioni \ MapsDemo \ src \ com \ esempio \ Android \ apis \ vista \

RotateView 
SmoothCanvas 

Estrarre classe RotateView interna al RotateView.java e aggiungere SmoothCanvas come classe interna di RotateView.java anziché 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> 

Il 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 
} 

} 

Aggiornamento: rotante Google MapView con Compass Esempio di progetto: https://www.dropbox.com/sh/c1encbc2lr63qd9/6C1C4hsrlT

+0

Puoi darmi una dimostrazione di lavoro completa? –

+0

Vedrò se avrò il tempo di fare una demo funzionante. – TouchBoarder

+0

@Nirav Ranpara - Ho aggiornato la risposta con un progetto di esempio di lavoro. – 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)); 

}