Google Maps API Android v2 - detect touch sur la carte

Je ne trouve pas d'exemple sur la façon d'intercepter le map touch sur la nouvelle API GoogleMaps V2.

j'ai besoin de savoir quand l'utilisateur touche la carte dans le but d'arrêter un thread (le centrage de la carte autour de ma position actuelle).

61
demandé sur Gaucho 2012-12-23 21:23:39

10 réponses

@ape a écrit une réponse ici sur la façon d'intercepter les clics de la carte, mais je dois intercepter les touches, puis il a suggéré le lien suivant dans un commentaire de sa réponse, comment gérer onTouch événement pour la carte dans Google Map API v2? .

cette solution semble être une solution de rechange possible, mais le code suggéré était incomplet. Pour cette raison, je l'ai réécrit et testé, et maintenant il fonctionne.

ici c'est le code de travail:

j'ai créé la classe MySupportMapFragment.java

import com.google.android.gms.maps.SupportMapFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MySupportMapFragment extends SupportMapFragment {
    public View mOriginalContentView;
    public TouchableWrapper mTouchView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
        mOriginalContentView = super.onCreateView(inflater, parent, savedInstanceState);
        mTouchView = new TouchableWrapper(getActivity());
        mTouchView.addView(mOriginalContentView);
        return mTouchView;
    }

    @Override
    public View getView() {
        return mOriginalContentView;
    }
}

j'ai même créé la classe TouchableWrapper.java:

import android.content.Context;
import android.view.MotionEvent;
import android.widget.FrameLayout;

public class TouchableWrapper extends FrameLayout {

    public TouchableWrapper(Context context) {
        super(context);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {

        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:
                  MainActivity.mMapIsTouched = true;
                  break;

            case MotionEvent.ACTION_UP:
                  MainActivity.mMapIsTouched = false;
                  break;
        }
        return super.dispatchTouchEvent(event);
    }
}

dans la disposition je le déclare ainsi:

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/mapFragment"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_alignParentBottom="true"
          android:layout_below="@+id/buttonBar"
          class="com.myFactory.myApp.MySupportMapFragment"
/>

Juste pour tester l'Activité principale, j'ai écrit:

public class MainActivity extends FragmentActivity {
    public static boolean mMapIsTouched = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
88
répondu Gaucho 2017-05-23 12:10:11

Voici une solution simple pour obtenir l'emplacement basé sur la sélection de l'utilisateur (cliquez sur l'option sur la carte)

  googleMap.setOnMapClickListener(new OnMapClickListener() {

            @Override
            public void onMapClick(LatLng arg0) {
                // TODO Auto-generated method stub
                Log.d("arg0", arg0.latitude + "-" + arg0.longitude);
            }
        });
40
répondu Sampath Kumar 2014-03-18 08:26:16

cette fonctionnalité et bien d'autres sont maintenant supportées:)

c'est la note du développeur(numéro 4636):

la version d'août 2016 présente un ensemble de nouveaux récepteurs de changement de caméra pour les événements de début, de fin et en cours. Vous pouvez également voir pourquoi la caméra bouge, qu'elle soit causée par des gestes de l'Utilisateur, des animations API intégrées ou des mouvements contrôlés par le développeur. Pour plus de détails, consultez le guide des événements de changement de caméra: https://developers.google.com/maps/documentation/android-api/events#camera-change-events

Voir aussi les notes de version: https://developers.google.com/maps/documentation/android-api/releases#august_1_2016

voici un extrait de code de la page de documentation

public class MyCameraActivity extends FragmentActivity implements
        OnCameraMoveStartedListener,
        OnCameraMoveListener,
        OnCameraMoveCanceledListener,
        OnCameraIdleListener,
        OnMapReadyCallback {

    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_camera);

        SupportMapFragment mapFragment =
            (SupportMapFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap map) {
        mMap = map;

        mMap.setOnCameraIdleListener(this);
        mMap.setOnCameraMoveStartedListener(this);
        mMap.setOnCameraMoveListener(this);
        mMap.setOnCameraMoveCanceledListener(this);

        // Show Sydney on the map.
        mMap.moveCamera(CameraUpdateFactory
                .newLatLngZoom(new LatLng(-33.87365, 151.20689), 10));
    }

    @Override
    public void onCameraMoveStarted(int reason) {

        if (reason == OnCameraMoveStartedListener.REASON_GESTURE) {
            Toast.makeText(this, "The user gestured on the map.",
                           Toast.LENGTH_SHORT).show();
        } else if (reason == OnCameraMoveStartedListener
                                .REASON_API_ANIMATION) {
            Toast.makeText(this, "The user tapped something on the map.",
                           Toast.LENGTH_SHORT).show();
        } else if (reason == OnCameraMoveStartedListener
                                .REASON_DEVELOPER_ANIMATION) {
            Toast.makeText(this, "The app moved the camera.",
                           Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onCameraMove() {
        Toast.makeText(this, "The camera is moving.",
                       Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onCameraMoveCanceled() {
        Toast.makeText(this, "Camera movement canceled.",
                       Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onCameraIdle() {
        Toast.makeText(this, "The camera has stopped moving.",
                       Toast.LENGTH_SHORT).show();
    }
}
17
répondu A.Alqadomi 2016-10-24 15:08:28

j'ai créé un FrameLayout vide superposé au-dessus du fragment Map dans la disposition. J'ai ensuite placé un onTouchListener sur cette vue pour savoir quand la carte a été touchée mais retourner false pour que le contact soit passé sur la carte.

<FrameLayout
    android:id="@+id/map_touch_layer"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

mapTouchLayer.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            Utils.logDebug(TAG, "Map touched!");
            timeLastTouched = System.currentTimeMillis();
            return false; // Pass on the touch to the map or shadow layer.
        }
    });
8
répondu Flyview 2015-08-15 07:10:04

https://developers.google.com/maps/documentation/android/reference/com/google/android/gms/maps/GoogleMap.OnMapClickListener

voir ce lien. Implémentez l'interface et remplissez la méthode onMapClick() ou celle dont vous avez besoin et définissez la onMapClickListener à la bonne implémentation.

public class YourActivity extends Activity implements OnMapClickListener {
    @Override
    protected void onCreate(Bundle icicle) { 
        super.onCreate(icicle);
        ...
        my_map.setOnMapClickListener(this)        
        ...
    }

    public void onMapClick (LatLng point) {
        // Do Something
    }
}
5
répondu adarsh 2012-12-23 17:51:18

Gaucho a une grande réponse, et vu les nombreuses critiques, j'ai pensé qu'il pourrait y avoir un besoin pour une autre mise en œuvre:

j'en avais besoin pour utiliser un auditeur pour pouvoir réagir au toucher et ne pas avoir à le vérifier constamment.

j'ai mis tout dans une classe qui peut être utilisé comme ceci:

mapFragment.setNonConsumingTouchListener(new TouchSupportMapFragment.NonConsumingTouchListener() {
    @Override
    public void onTouch(MotionEvent motionEvent) {
        switch (motionEvent.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                // map is touched
                break;
            case MotionEvent.ACTION_UP:
                // map touch ended
                break;
            default:
                break;
            // use more cases if needed, for example MotionEvent.ACTION_MOVE
        }
    }
});

où le mapfragment doit être de type TouchSupportMapFragment et dans le layout xml ceci la ligne est nécessaire:

<fragment class="de.bjornson.maps.TouchSupportMapFragment"
...

Voici la classe:

package de.bjornson.maps;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.google.android.gms.maps.SupportMapFragment;

public class TouchSupportMapFragment extends SupportMapFragment {
    public View mOriginalContentView;
    public TouchableWrapper mTouchView;
    private NonConsumingTouchListener mListener;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
        mOriginalContentView = super.onCreateView(inflater, parent, savedInstanceState);
        mTouchView = new TouchableWrapper(getActivity());
        mTouchView.addView(mOriginalContentView);
        return mTouchView;
    }

    @Override
    public View getView() {
        return mOriginalContentView;
    }

    public void setNonConsumingTouchListener(NonConsumingTouchListener listener) {
        mListener = listener;
    }

    public interface NonConsumingTouchListener {
        boolean onTouch(MotionEvent motionEvent);
    }

    public class TouchableWrapper extends FrameLayout {

        public TouchableWrapper(Context context) {
            super(context);
        }

        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            if (mListener != null) {
                mListener.onTouch(event);
            }
            return super.dispatchTouchEvent(event);
        }
    }
}
5
répondu Björn Kechel 2016-08-04 14:57:07
  // Initializing
    markerPoints = new ArrayList<LatLng>();

    // Getting reference to SupportMapFragment of the activity_main
    SupportMapFragment sfm = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);

    // Getting Map for the SupportMapFragment
    map = sfm.getMap();

    // Enable MyLocation Button in the Map
    map.setMyLocationEnabled(true);

    // Setting onclick event listener for the map
    map.setOnMapClickListener(new OnMapClickListener() {

        @Override
        public void onMapClick(LatLng point) {

            // Already two locations
            if(markerPoints.size()>1){
                markerPoints.clear();
                map.clear();
            }

            // Adding new item to the ArrayList
            markerPoints.add(point);

            // Creating MarkerOptions
            MarkerOptions options = new MarkerOptions();

            // Setting the position of the marker
            options.position(point);


            if(markerPoints.size()==1){
                options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
            }else if(markerPoints.size()==2){
                options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
            }

            // Add new marker to the Google Map Android API V2
            map.addMarker(options);

            // Checks, whether start and end locations are captured
            if(markerPoints.size() >= 2){
                LatLng origin = markerPoints.get(0);
                LatLng dest = markerPoints.get(1);

            //Do what ever you want with origin and dest
            }
        }
    });
1
répondu Pratibha Sarode 2016-02-11 10:08:59

pour Mono amants:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using Android.Gms.Maps;

namespace apcurium.MK.Booking.Mobile.Client.Controls
{
    public class TouchableMap : SupportMapFragment
    {
        public View mOriginalContentView;

        public TouchableWrapper Surface;

        public override View OnCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
        {
            mOriginalContentView = base.OnCreateView(inflater, parent, savedInstanceState);
            Surface = new TouchableWrapper(Activity);
            Surface.AddView(mOriginalContentView);
            return Surface;
        }

        public override View View
        {
            get
            {
                return mOriginalContentView;
            }
        }
    }

    public class TouchableWrapper: FrameLayout {

        public event EventHandler<MotionEvent> Touched;

        public TouchableWrapper(Context context) :
        base(context)
        {
        }

        public TouchableWrapper(Context context, IAttributeSet attrs) :
        base(context, attrs)
        {
        }

        public TouchableWrapper(Context context, IAttributeSet attrs, int defStyle) :
        base(context, attrs, defStyle)
        {
        }

        public override bool DispatchTouchEvent(MotionEvent e)
        {
            if (this.Touched != null)
            {
                this.Touched(this, e);
            }

            return base.DispatchTouchEvent(e);
        }
    }
}
1
répondu Léon Pelletier 2016-02-26 16:39:36

@Gaucho MySupportMapFragment sera évidemment utilisé par un autre fargment ou activité(où il pourrait y avoir plus d'éléments de vue que le fragment de carte). Alors comment peut-on envoyer cet événement au prochain fragment où il doit être utilisé. Avons-nous besoin d'écrire à nouveau une interface pour faire cela?

0
répondu user2201332 2016-03-21 13:33:31

j'ai une solution plus simple diférente de la TouchableWrapper et cela fonctionne avec la dernière version de play-services-maps:10.0.1 . Cette solution utilise uniquement les événements maps et n'utilise pas de vues personnalisées. N'utilise pas de fonctions obsolètes et aura probablement le support de plusieurs versions.

tout d'abord, vous avez besoin d'une variable flag qui stocke si la carte est déplacée par une animation ou par une entrée de l'utilisateur (ce code suppose que chaque mouvement de caméra qui n'est pas déclenché par une animation est déclenché par l'utilisateur)

GoogleMap googleMap;
boolean movedByApi = false;

votre fragment ou activité doit mettre en œuvre GoogleMap.OnMapReadyCallback , GoogleMap.CancelableCallback

public class ActivityMap extends Activity implements OnMapReadyCallback, GoogleMap.CancelableCallback{
    ...
}

et cela vous oblige à mettre en œuvre les méthodes onMapReady , onFinish , onCancel . Et l'objet googleMap dans onMapReady doit définir un eventilistener pour le déplacement de la caméra

@Override
public void onMapReady(GoogleMap mMap) {
    //instantiate the map
    googleMap = mMap;

    [...]  // <- set up your map

    googleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
        @Override
        public void onCameraMove() {
            if (movedByApi) {
                Toast.makeText(ActivityMap.this, "Moved by animation", Toast.LENGTH_SHORT).show();

                [...] // <-- do something whe you want to handle api camera movement
            } else {
                Toast.makeText(ActivityMap.this, "Moved by user", Toast.LENGTH_SHORT).show();

                [...] // <-- do something whe you want to handle user camera movement
            }
        }
    });
}
@Override
public void onFinish() {
    //is called when the animation is finished
    movedByApi = false;
}
@Override
public void onCancel() {
    //is called when the animation is canceled (the user drags the map or the api changes to a ne position)
    movedByApi = false;
}

et enfin son parieur Si vous créez une fonction générique pour déplacer la carte

public void moveMapPosition(CameraUpdate cu, boolean animated){
    //activate the flag notifying that the map is being moved by the api
    movedByApi = true;
    //if its not animated, just do instant move
    if (!animated) {
        googleMap.moveCamera(cu);
        //after the instant move, clear the flag
        movedByApi = false;
    }
    else
        //if its animated, animate the camera
        googleMap.animateCamera(cu, this);
}

ou juste à chaque fois que vous déplacez la carte, activez le drapeau avant l'animation

movedByApi = true;
googleMap.animateCamera(cu, this);

j'espère que cela aidera!

0
répondu Sander Rito 2017-01-10 16:52:45