2009-12-02 21 views
16

Ich schreibe eine Android-App, wo eine der Funktionen ist, dass die Karte entsprechend dem Kompass drehen wird (dh wenn das Telefon nach Osten zeigt, wird die Karte so ausgerichtet, dass die Ostseite der Karte ist oben). Frühere Antworten, die ich gefunden habe, schlagen vor, die onDraw() -Methode in mapView zu schreiben, jedoch hat die API die Methode auf final gesetzt, so dass sie nicht überschrieben werden kann. Als Ergebnis habe ich versucht, wie so die dispatchDraw() Methode zu überschreiben:Karte in Android drehen

Hinweis:

-Kompass ist ein boolean, dass wenn sie wahr ist, die Ansicht

-substituierte ist eine Variable vom Typ float drehen, die Grade hat dass die Ansicht

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

warum tun Sie OnDraw außer Kraft setzen müssen, Sie nicht können animiere den Blick innerhalb deiner Aktivität? – schwiz

+0

@Matthew: hast du Antwort, wenn ja, bitte gib mir Lösung –

Antwort

1

Es soll so etwas wie diese drehen sollte:

@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

Hat es für Sie funktioniert? Es hat nicht für mich funktioniert. –

3

Aus der Dokumentation:

protected void dispatchDraw (Canvas Leinwand)

lost aufgerufen, um die untergeordneten Ansichten zu ziehen. Dies kann von abgeleiteten Klassen außer Kraft gesetzt werden, um Kontrolle zu erlangen, kurz bevor ihre Kinder gezeichnet werden (aber nachdem ihre eigene Ansicht gezeichnet wurde).

So zwingende dispatchDraw bereits gezogen worden

Eine Lösung könnte die MapView als Kind eines anderen Custom (eine Unterklasse von Viewgroup) sein, nicht gut, wie die Hauptkarte Ansicht ist hinzufügen und dann verwenden die dispatchDraw-Methode von CustomView, um die MapView (jetzt ein untergeordnetes Objekt) zu rotieren. Also in xml würde man so etwas tun:

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

Werfen Sie einen Blick auf MapsDemo Beispiele in ANDROID_SDK\add-ons\addon-google_apis-google_inc_-7\samples\MapsDemo. Es hat Rotations-Karten-Demo.

8

Dank Pheelicks und Nikita Koksharovs Antworten, schalte ich die Rotation eines Mapview entsprechend dem Kompass ein/aus.

Zuerst müssen Sie die zwei innere Klasse von MapViewCompassDemo.java gefunden auf: Android_SDK_ Tools \ Add-ons \ Addon-google_apis-google - # \ Samples \ MapsDemo \ src \ com \ Beispiel \ android \ apis \ Ansicht \

RotateView 
SmoothCanvas 

Extrahieren der inneren Klasse RotateView zu RotateView.java und hinzufügen SmoothCanvas als innere Klasse von RotateView.java anstelle von MapViewCompassDemo.java

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

Anzeige.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> 

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

} 

Update: Rotierende Google MapView mit Compass Beispielprojekt: https://www.dropbox.com/sh/c1encbc2lr63qd9/6C1C4hsrlT

+0

Kannst du mir eine vollständige Demo geben? –

+0

Ich werde sehen, ob ich die Zeit habe, eine funktionierende Demo zu machen. – TouchBoarder

+0

@Nirav Ranpara - Ich habe die Antwort mit einem funktionierenden Beispielprojekt aktualisiert. – 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)); 

}