在Android中旋转MapView

我正在编写一个Android应用程序,其中一个function是地图将根据指南针进行旋转(即,如果手机指向东,地图的方向将使地图的东侧位于顶部)。 以前的答案,我发现build议在mapView中编写onDraw()方法,但是,api将方法更改为最终,所以它不能被覆盖。 因此,我试图覆盖dispatchDraw()方法,如下所示:

注意:

-compass是一个布尔值,如果为true,则旋转视图

-bearing是一个浮点型variables,它具有视图应该旋转的angular度

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

Solutions Collecting From Web of "在Android中旋转MapView"

感谢pheelicks和Nikita Koksharov的回答,我设法根据指南针打开/closuresmapv​​iew的旋转。

首先,您需要在以下位置findMapViewCompassDemo.java两个内部类:Android_SDK_ Tools \ add-ons \ addon-google_apis-google – #\ samples \ MapsDemo \ src \ com \ example \ android \ apis \ view \

 RotateView SmoothCanvas 

将内部类RotateView提取到RotateView.java并将 SmoothCanvas 添加为 RotateView.java的内部类,而不是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> 

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

更新:使用Compass示例项目旋转Google MapView: https : //www.dropbox.com/sh/c1encbc2lr63qd9/6C1C4hsrlT

从文档:

保护无效dispatchDraw(canvascanvas)

通过绘制来绘制子视图。 派生类可能会覆盖这个类,以便在其子项被抽取之前(但是在它自己的视图被绘制之后)获得控制权。

所以覆盖dispatchDraw是不好的,因为已经绘制了主地图视图

一种解决scheme可能是将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> 

它应该是这样的:

 @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(); } } 

查看ANDROID_SDK\add-ons\addon-google_apis-google_inc_-7\samples\MapsDemo 。 它有旋转地图演示。

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