карты Android Авто-поворот

Если вы открываете приложение Google maps, в правом верхнем углу экрана есть кнопка, которую вы можете нажать, чтобы центрировать карту в своем текущем местоположении. Затем значок кнопки изменяется. Если вы снова нажмете ту же кнопку, карта автоматически повернется в зависимости от курса компаса. Другими словами, карта становится эгоцентрической (в отличие от аллоцентрической АКА Север всегда вверх).

Google недавно запустил maps API V2 для Android, и мне это нравится больше, чем старый. По умолчанию, android maps V2 будет включать в себя кнопку" центр на месте". Однако нажатие на него несколько раз не включает автоматическое вращение; он просто пытается снова центрировать карту на вашем местоположении.

кто-нибудь знает, как я могу автоматически поворачивать карту с помощью maps API v2 так же, как приложение google maps? Должен ли я реализовать эту функциональность самостоятельно или это в API, и я просто не вижу ее? Я ценю любую помощь.

4 ответов


хорошо вот как я думаю, что это должно быть сделано через год. Пожалуйста, поправьте меня, если вы заметили какие-либо проблемы.

большая часть следующего кода имеет дело с несоответствием между системами координат. Я использую датчик вектора вращения. Из документов: Y is tangential to the ground at the device's current location and points towards magnetic north. подшипник в Google maps, с другой стороны, кажется, указывает на истинный север. на этой странице показано, как выполняется преобразование

1) получите текущее склонение от вашего текущего GPS местоположение

@Override
public void onLocationChanged(Location location) {
    GeomagneticField field = new GeomagneticField(
            (float)location.getLatitude(),
            (float)location.getLongitude(),
            (float)location.getAltitude(),
            System.currentTimeMillis()
        );

    // getDeclination returns degrees
    mDeclination = field.getDeclination();
} 

2) вычислить подшипник от склонения и магнитного Севера

    @Override
public void onSensorChanged(SensorEvent event) {
    if(event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
        SensorManager.getRotationMatrixFromVector(
                mRotationMatrix , event.values);
        float[] orientation = new float[3];
        SensorManager.getOrientation(mRotationMatrix, orientation);
        float bearing = Math.toDegrees(orientation[0]) + mDeclination;
        updateCamera(bearing);  
    }
}

3) обновление карты

private void updateCamera(float bearing) {
    CameraPosition oldPos = mMap.getCameraPosition();

    CameraPosition pos = CameraPosition.builder(oldPos).bearing(bearing).build();
            mMap.moveCamera(CameraUpdateFactory.newCameraPosition(pos));
}

Я успешно реализовал решение aleph_null, и здесь я добавлю некоторые детали, которые не упоминаются в принятом решении:

для вышеуказанного решения для работы вам необходимо реализовать android.аппаратура.Интерфейс SensorEventListener.

вам также нужно зарегистрироваться в SensorEventListener в методах onResume и onPause следующим образом:

@Override
    protected void onResume() {
     super.onResume();
     mSensorManager.registerListener(this,
             mRotVectSensor,
             SensorManager.SENSOR_STATUS_ACCURACY_LOW);
    }

@Override
protected void onPause() {
    // unregister listener
    super.onPause();
    mSensorManager.unregisterListener(this);
}

примечание к "@Bytecode": чтобы избежать мерцания, используйте низкое значение для периода выборки, что-то как метод SensorManager.SENSOR_STATUS_ACCURACY_LOW.

Я также заметил, что датчик отправляет иногда больше данных, чем устройство может обрабатывать, и в результате камера карты начинает двигаться странным образом!

чтобы контролировать объем данных, обрабатываемых onSensorChanged, я предлагаю следующую реализацию:

@Override
public void onSensorChanged(SensorEvent event) {
    if(event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
        SensorManager.getRotationMatrixFromVector(
                mRotationMatrix, event.values);
        float[] orientation = new float[3];
        SensorManager.getOrientation(mRotationMatrix, orientation);
        if (Math.abs(Math.toDegrees(orientation[0]) - angle) > 0.8) {
            float bearing = (float) Math.toDegrees(orientation[0]) + mDeclination;
            updateCamera(bearing);
        }
        angle = Math.toDegrees(orientation[0]);
    }
}

это возможно путем регистрации вашего приложения с помощью прослушивателя датчика для ориентации и получения угла относительно истинного Севера внутри onSensorChanged и обновления камеры соответственно. Угол можно использовать для подшипника. Можно использовать следующий код:

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

}

Извините, вам придется реализовать его самостоятельно с помощью датчик диспетчере и камера

Если бы эти функции были доступны для Map api V2, они, безусловно, были бы либо на GoogleMap или UiSettings