Подтвердить что ты не робот

Поверните MapView в Android

Я пишу приложение для Android, в котором одна из функций заключается в том, что карта будет вращаться в соответствии с компасом (т.е. если телефон указывает на восток, карта будет ориентирована так, чтобы восточная сторона карты была сверху), Предыдущие ответы, которые, как я нашел, были предложены для написания метода onDraw() в mapView, однако api изменил метод на final, чтобы его нельзя было перезаписать. В результате я попытался перезаписать метод dispatchDraw() следующим образом:

Примечание:

-compass является логическим, если true, поверните представление

-bearing - это переменная с плавающей точкой, которая имеет градусы, которые вид должен вращать.

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

Ответ 1

Благодаря ответам pheelicks и Nikita Koksharov, мне удается включить/выключить поворот карты в соответствии с компасом.

Сначала вам понадобится два внутренних класса MapViewCompassDemo.java, найденных по адресу: Android_SDK_ Tools\add-ons\addon-google_apis-google - #\samples\MapsDemo\SRC\COM\например\Android\APIs\вид\

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
}

}

Update: Поворот Google MapView с помощью проекта Compass Project: https://www.dropbox.com/sh/c1encbc2lr63qd9/6C1C4hsrlT

Ответ 2

Из документов:

защищенный void dispatchDraw (холст холста)

Вызывается рисованием для рисования дочерних просмотров. Это может быть переопределено производными классами, чтобы получить контроль непосредственно перед его дочерними элементами (но после того, как его собственное представление было нарисовано).

Таким образом, переопределение dispatchDraw не подходит, поскольку основное представление карты уже нарисовано

Одним из решений может быть добавление MapView в качестве дочернего элемента другого CustomView (подкласс класса ViewGroup), а затем использование метода dispatchDraw CustomView для поворота 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>

Ответ 3

Это должно быть примерно так:

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

Ответ 4

Взгляните на примеры MapsDemo в ANDROID_SDK\add-ons\addon-google_apis-google_inc_-7\samples\MapsDemo. Он имеет демографическую карту вращения.

Ответ 5

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

}