2009-12-02 58 views
16

我正在編寫一個Android應用程序,其中一個功能是地圖將根據指南針進行旋轉(即,如果手機指向東,則地圖將定向爲使地圖的東側在最上面)。以前的答案,我發現建議在mapView中編寫onDraw()方法,但是,api將方法更改爲final,因此它不能被覆蓋。其結果是我試圖覆蓋dispatchDraw()方法如下所示:在Android中旋轉MapView

注:

-compass是一個布爾值,如果爲真,旋轉視圖

荷瘤是具有度的浮點變量該視圖應轉動

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

爲什麼你需要重寫的onDraw,你能不能只在您的活動中爲視圖添加動畫? – schwiz 2010-11-30 04:51:52

+0

@Matthew:你有沒有得到答案,如果是的話,請給我解決方案 – 2012-10-23 12:15:48

回答

1

應該是這樣的:

@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

它是否適合你?它沒有爲我工作。 – 2010-10-19 17:03:10

3

從文檔:

保護無效dispatchDraw(帆布油畫)

通過抽籤調用,以繪製子視圖。這可能會被派生類重寫,以便在子對象被繪製之前獲得控制權(但在繪製自己的視圖之後)。

所以覆蓋dispatchDraw是沒有好爲主要地圖視圖已經被繪製

一種解決方案可能是的MapView添加爲另一CustomView的孩子(一個子類的ViewGroup的),然後使用CustomView的dispatchDraw方法來繪製MapView(現在是一個孩子)的旋轉。所以在xml中你可以做類似的事情:

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

看看ANDROID_SDK\add-ons\addon-google_apis-google_inc_-7\samples\MapsDemo中的MapsDemo示例。它有旋轉地圖演示。

8

感謝pheelicks和Nikita Koksharov的回答,我設法根據指南針打開/關閉mapv​​iew的旋轉。

首先,你將需要兩個內部MapViewCompassDemo.java的發現:Android_SDK_工具\插件\插件 - google_apis - 谷歌 - #\樣本\ MapsDemo的\ src \ COM \例子\機器人\的API \視圖\

RotateView 
SmoothCanvas 

提取內部類RotateView到RotateView.java添加 SmoothCanvas作爲內部類RotateView.java代替MapViewCompassDemo.java

的0
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> 

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

} 

更新: 旋轉谷歌MapView的羅盤示例項目:https://www.dropbox.com/sh/c1encbc2lr63qd9/6C1C4hsrlT

+0

你能給我完整的工作演示嗎? – 2012-10-23 11:46:19

+0

我會看看我是否有時間做一個工作演示。 – TouchBoarder 2012-10-25 05:59:14

+0

@Nirav Ranpara - 我已經用一個工作示例項目更新了答案。 – TouchBoarder 2012-10-28 00:54:02

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

}