2009-12-02 57 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)); 

}