ジェスチャーの処理

利用開始の例からわかるように、マップ ビューでは、ピンチやダブルタップでズームインなど、一般的なすべてのマップジェスチャがデフォルトでサポートされています。 次の表に、使用可能なジェスチャと、マップ上の対応するデフォルトの動作の概要を示します。

1 本の指で画面をタップします。 このジェスチャには、定義済みのマップアクションがありません。
マップを一定の量だけ拡大 するには、 1 本の指で画面を 2 回タップします。
1 本の指を押して画面に移動します。 このジェスチャには、定義済みのマップアクションがありません。
マップを移動 するには、 1 本の指を画面に合わせて押し続け、任意の方向に動かします。 指を持ち上げると、マップが少し勢いをつけて動き続けます。
マップを傾けるに は、 2 本の指を画面に合わせて押し続け、垂直に動かします。 他の方向の動作は事前に定義されていません。
一定の量だけズームアウトするに は、 2 本の指で画面をタップします。
連続的にズームインまたはズームアウトする には、 2 本の指を押したまま画面に移動し、その間の距離を増減します。
マップを連続的に回転させるに は、 2 本の指を画面に合わせて押し続け、両方を回転するか、いずれかを動かして、マップの角度を変更します。

HERE SDK for Android では、次のジェスチャがサポートされています。

  • タップ : TapListener
  • ダブルタップ : DoubleTapListener
  • 長押し : LongPressListener
  • パン : PanListener
  • 2 本指でパン : TwoFingerPanListener
  • 2 本指でタップ : TwoFingerTapListener
  • ピンチ回転 : PinchRotateListener

各リスナーには、ユーザーが検出可能なアクション(特定のジェスチャの開始時や終了時など)を実行するたびに通知する専用のコールバックがあります。 通常は、ジェスチャが検出された後に、マップ マーカーを長押しした後に配置するなど、特定の動作をアプリケーションに追加します。

同じジェスチャには、一度に 1 つのリスナーのみを設定できます。

マップの操作を制御

リスナーを設定しても、ジェスチャのデフォルトのマップ動作には影響がありません。 個別に制御できます。 既定では、マップをダブルタップしたときの拡大など、すべての標準的な動作が有効になっています。

たとえば、次のように、ダブルタップ ( ズームイン ) および 2 本指タップ ( ズームアウト ) のデフォルトのマップジェスチャの動作を無効にできます。

mapView.getGestures().disableDefaultAction(GestureType.DOUBLE_TAP);
mapView.getGestures().disableDefaultAction(GestureType.TWO_FINGER_TAP);

既定のマップアクションを無効にしても、ジェスチャイベントをリッスンできます。 これは、例えば独自のズーム動作を実装するために、ジェスチャのデフォルトのアクションをオフにする場合に役立ちます。 タップと長押しを除くすべてのジェスチャで、デフォルトのマップアクションが提供されます。 詳細については、上の概要を参照してください。

デフォルトのマップジェスチャの動作を戻すには、次のように呼び出します。

mapView.getGestures().enableDefaultAction(GestureType.DOUBLE_TAP);
mapView.getGestures().enableDefaultAction(GestureType.TWO_FINGER_TAP);

ジェスチャーリスナーを添付

ジェスチャーリスナーをマップ ビューに添付する方法の例を見てみましょう。 マップ ビューでは、各ジェスチャに固有の setter が提供されています。 リスナーを設定するとすぐに、専用のコールバック (TapListener の場合は onTap()) を介して、そのジェスチャに関連するすべてのイベントを受信します。

private void setTapGestureHandler(MapView mapView) {
    mapView.getGestures().setTapListener(new TapListener() {
        @Override
        public void onTap(@NonNull Point2D touchPoint) {
            GeoCoordinates geoCoordinates = mapView.viewToGeoCoordinates(touchPoint);
            Log.d(TAG, "Tap at: " + geoCoordinates);
        }
    });
}

リスナーを設定するとすぐに、ジェスチャが検出されたことを知らせる通知が届き始めます。

touchPointは 、ジェスチャが発生したMapView座標を指定します。 mapView.viewToGeoCoordinates(touchPoint)を呼び出すことで 、ピクセルを地理座標に変換できます ( 上図を参照 ) 。

同様に、リスニングを停止するには、以下をコールします。

mapView.getGestures().setTapListener(null);

連続したジェスチャ ( 長押し、ピンチ、パン、 2 本の指のパンなど ) の場合 、ジェスチャの状態BEGIN はジェスチャが検出されたことを示します。 指がディスプレイに触れている間は、END状態が指が離されたことを示すか、CANCEL状態がジェスチャ検出がキャンセルされたことを示すまで、UPDATE状態を受け取ることがあります。

private void setLongPressGestureHandler(MapView mapView) {
    mapView.getGestures().setLongPressListener(new LongPressListener() {
        @Override
        public void onLongPress(@NonNull GestureState gestureState, @NonNull Point2D touchPoint) {
            GeoCoordinates geoCoordinates = mapView.viewToGeoCoordinates(touchPoint);

            if (gestureState == GestureState.BEGIN) {
                Log.d(TAG, "LongPress detected at: " + geoCoordinates);
            }

            if (gestureState == GestureState.UPDATE) {
                Log.d(TAG, "LongPress update at: " + geoCoordinates);
            }

            if (gestureState == GestureState.END) {
                Log.d(TAG, "LongPress finger lifted at: " + geoCoordinates);
            }

            if (gestureState == GestureState.CANCEL) {
                Log.d(TAG, "Map view lost focus. Maybe a modal dialog is shown or the app is sent to background.");
            }
        }
    });
}

たとえば、長押しのイベントが検出された後も、ユーザーが指を画面に置いたままにしたり、移動したりすることがあります。 ただし BEGIN 、長押しジェスチャが検出された時点でマークされるのはイベントのみです。

マップ上にマップ マーカーを配置する場合は、長押しのジェスチャが便利です。 この例については、アプリの検索 例を参照してください。

連続していないジェスチャ ( タップ、ダブルタップ、 2 本の指タップなど ) の 場合、ジェスチャイベントを処理するためにGestureState は必要ありません。

パンジェスチャを使用すると、マップをスワイプして移動することがあります。これにより、ジェスチャはすでに終了しており、すべての指が持ち上げられているにもかかわらず、移動が継続されます。 マップの移動がいつ終了したかを検出するには、MapIdleListener を使用します。 インスタンスHereMapに追加でき、インスタンスMapView から取得できます。

GitHub では 、ジェスチャ のサンプルアプリの一部として、コードスニペットおよびその他の使用例を利用できます。

チュートリアル : マップの操作をカスタマイズ

すでに確認したように、既定ではダブルタップジェスチャによって、都市レベルから通りのレベルに近い場所など、マップが個別のステップでズームされます。 このようなデフォルトのマップジェスチャアクションを無効にして独自のビヘイビアーを実装することも、既存のビヘイビアーに必要なアクションを追加することもできます。

必要に応じて、プラットフォームジェスチャ操作と HERE SDK ジェスチャ検出を組み合わせることもできます。 HERE SDK では、利便性のために、一般的なマップジェスチャに重点を置いているため、すべての種類の低レベルのジェスチャイベントを提供するわけではありません。 より詳細な制御が必要な場合は、 HERE SDK で利用できるジェスチャ処理とネイティブの Android ジェスチャ検出をいつでも組み合わせることができます。

このチュートリアルで は、カスタムズームアニメーションを有効にする方法を示します。 ユーザー がダブルタップまたは 2 本の指でタップした後、マップが徐々に拡大または縮小されます。 ズームのアニメーションはしばらくすると遅くなります。

カスタムのズーム動作を追加

アニメーションから始めましょう。 このために、 Android の アニメーションフレームワークValueAnimator を使用して、特定の開始値と終了値の間で補間を行うことができます。

便宜上、GestureMapAnimatorという名前の新しいクラスを作成します。このクラスは、ジェスチャに関連するすべてのアニメーションを処理する必要があります。 マップをカメラでズームする必要があるため、マップのMapCamera インスタンスへの参照が必要です。

既定では、マップは、途中のステップを使わずに、指がマップに触れる位置で、 1 つの個別のステップでズームイン / ズームアウトします。

必要なジェスチャイベントをフックしてみましょう。

mapView.getGestures().disableDefaultAction(GestureType.DOUBLE_TAP);
mapView.getGestures().disableDefaultAction(GestureType.TWO_FINGER_TAP);

mapView.getGestures().setDoubleTapListener(new DoubleTapListener() {
    @Override
    public void onDoubleTap(@NonNull Point2D touchPoint) {
        // Start our custom zoom in animation.
        gestureMapAnimator.zoomIn(touchPoint);
    }
});

mapView.getGestures().setTwoFingerTapListener(new TwoFingerTapListener() {
    @Override
    public void onTwoFingerTap(@NonNull Point2D touchCenterPoint) {
        // Start our custom zoom out animation.
        gestureMapAnimator.zoomOut(touchCenterPoint);
    }
});

ここにはマジックはありません。2 つのジェスチャイベントをリッスンするだけです。 既定のズーム動作が事前に無効になっていることを確認する必要があります。 上記のzoomIn()メソッドおよびzoomOut()メソッドは、以下に示すGestureMapAnimatorの新しいメソッドにつながります。

// Starts the zoom in animation.
public void zoomIn(Point2D touchPoint) {
    zoomOrigin = touchPoint;
    startZoomAnimation(true);
}

// Starts the zoom out animation.
public void zoomOut(Point2D touchPoint) {
    zoomOrigin = touchPoint;
    startZoomAnimation(false);
}

マップ のどこを拡大または縮小するかを把握するために、 zoomOriginを保存します。

新しい GestureMapAnimator クラス内でのstartZoomAnimation()の実装では 、次のValueAnimatorを使用します。

private void startZoomAnimation(boolean zoomIn) {
    stopAnimations();

    // A new Animator that zooms the map.
    zoomValueAnimator = createZoomValueAnimator(zoomIn);

    // Start the animation.
    zoomValueAnimator.start();
}

private ValueAnimator createZoomValueAnimator(boolean zoomIn) {
    ValueAnimator zoomValueAnimator = ValueAnimator.ofFloat(0.1F, 0);
    zoomValueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
    zoomValueAnimator.addUpdateListener(animation -> {
        // Called periodically until zoomVelocity is zero.
        float zoomVelocity = (float) animation.getAnimatedValue();
        double zoomFactor = 1;
        zoomFactor = zoomIn ? zoomFactor + zoomVelocity : zoomFactor - zoomVelocity;
        // zoomFactor values > 1 will zoom in and values < 1 will zoom out.
        camera.zoomBy(zoomFactor, zoomOrigin);
    });

    long halfSecond = 500;
    zoomValueAnimator.setDuration(halfSecond);

    return zoomValueAnimator;
}

0.1 ~ 0 の値を補間するには、ValueAnimatorを使用します。 これらの値によって、ズーム速度が決まります。 AccelerateDecelerateInterpolator には、中間値があり、最後にスローダウンの影響があります ValueAnimator に設定したリスナー は 、zoomVelocityが 0 に達するまで定期的に実行されます。 zoomVelocity は、マップのズームに使用できるアニメーション値です。 ズーム倍率を設定する引数として使用します。 zoomVelocity がゆっくりと 0 に達すると、結果のズームステップのサイズがどんどん小さくなります。

上の図では、保存したタッチの起点zoomOriginを使用して、指が画面に触れたポイントにズームインします。 ズームアウトする場合は、 2 本の指でタップするジェスチャの間のポイントになります。 カメラ のメソッドzoomBy() は、指定した場所で離散的なズームステップを実行するように処理します。

マップを拡大または 縮小するかどうかを示すブール型値が提供されます。 これにより、両方のズームケースでコードを使用できます。 唯一の違い は、アニメーション化された値zoomVelocityが現在のズーム係数に加算または減算されることです。

ズーム倍率では、マップのズームインまたはズームアウトする距離を指定します。 ズーム係数 1 を指定しても、現在のズーム レベルは変更されません。

上記のメソッドstopAnimations()は、対応するインスタンス ValueAnimator の進行中のアニメーションをキャンセルするだけです。

public void stopAnimations() {
    if (zoomValueAnimator != null) {
        zoomValueAnimator.cancel();
    }
}

これで、画面遷移が終了します。上記のコードスニペットは、ご自身のニーズに合わせて自由に変更できます。 たとえば、さまざまな補間法、さまざまなアニメーション値、または異なるアニメーション期間を使用して再生を開始します。

」に一致する結果は 件です

    」に一致する結果はありません