web-dev-qa-db-ja.com

androidマップの自動回転

Googleマップアプリを開くと、画面の右上にボタンがあり、このボタンを押すと、現在地の中心にマップを配置できます。ボタンのアイコンが変わります。同じボタンをもう一度押すと、コンパスの方位に基づいてマップが自動回転します。言い換えると、マップは自我中心になります(同心円のAKAノースが常に上にあるのとは対照的に)。

Googleは最近AndroidのMaps API V2をリリースしましたが、確かに古いものよりも気に入っています。デフォルトでは、Android Maps V2には「center on location "ボタンを押します。ただし、複数回押しても自動回転は有効になりません。単に地図を現在地の中心に配置しようとするだけです。

Googleマップアプリと同じように、maps API v2を使用してマップを自動回転させる方法を誰かが知っていますか?この機能を自分で実装する必要がありますか、それともAPIにありますか?私はすべての助けに感謝します。

21
aleph_null

わかりました、1年後に行うべきだと私は思います。問題を見つけたら訂正してください。

次のコードのほとんどは、座標系間の不一致を扱います。回転ベクトルセンサーを使用しています。ドキュメントから:Y is tangential to the ground at the device's current location and points towards magnetic north.一方、グーグルマップの方位は真北を指しているようです。 このページは変換がどのように行われるかを示します

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

Aleph_nullソリューションの実装に成功しました。ここでは、承認されたソリューションで言及されていない詳細をいくつか追加します。

上記のソリューションを機能させるには、Android.hardware.SensorEventListenerインターフェースを実装する必要があります。

次のように、onResumeおよびonPauseメソッドでSensorEventListenerに登録する必要もあります。

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

アプリケーションを向きのセンサーリスナーに登録し、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));

}
2
Prashant

センサーマネージャーカメラ を使用して自分で実装する必要があります

これらの関数がマップAPI V2で使用できる場合、それらは確かに GoogleMap または iSettings のいずれかにあります。

0
Budius