it-swarm.com.de

Google Maps Android API v2 - Erkennen von Berührung auf der Karte

Ich kann kein Beispiel finden, wie die Kartenberührung in der neuen Google Maps API Version 2 abgefangen wird.

Ich muss wissen, wann der Benutzer die Karte berührt, um einen Thread zu stoppen (die Zentrierung der Karte um meinen aktuellen Standort).

65
Gaucho

@ape schrieb hier eine Antwort, wie die Kartenklicks abgefangen werden sollen, aber ich muss die Berührungen abfangen, und dann schlug er den folgenden Link in einem Kommentar der Antwort vor: So behandeln Sie das onTouch-Ereignis für die Karte in Google Map API v2 ? .

Diese Lösung scheint eine mögliche Problemumgehung zu sein, der vorgeschlagene Code war jedoch unvollständig. Aus diesem Grund habe ich es neu geschrieben und getestet, und jetzt funktioniert es.

Hier ist der Arbeitscode:

Ich habe die Klasse MySupportMapFragment.Java erstellt

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

Ich habe sogar die Klasse TouchableWrapper.Java erstellt:

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

Im Layout erkläre ich es so:

<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"
/>

Nur zum Test in der Hauptaktivität habe ich nur folgendes geschrieben:

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
89
Gaucho

Hier ist eine einfache Lösung, um den Standort basierend auf der Benutzerauswahl abzurufen (Option auf Karte klicken)

  googleMap.setOnMapClickListener(new OnMapClickListener() {

            @Override
            public void onMapClick(LatLng arg0) {
                // TODO Auto-generated method stub
                Log.d("arg0", arg0.latitude + "-" + arg0.longitude);
            }
        });
42
Sampath Kumar

Diese Funktion und viele mehr werden jetzt unterstützt :)

dies ist der Entwicklerhinweis (Problem 4636):

Die Version vom August 2016 stellt eine Reihe neuer Kamerawechsel-Listener für den Start der Kamera, laufende und Endereignisse vor. Sie können auch sehen, warum sich die Kamera bewegt, sei es durch Benutzergesten, integrierte API-Animationen oder durch Entwickler gesteuerte Bewegungen. Weitere Informationen finden Sie im Handbuch zu Kameraänderungsereignissen: https://developers.google.com/maps/documentation/Android-api/events#camera-change-events

Beachten Sie auch die Versionshinweise: https://developers.google.com/maps/documentation/Android-api/releases#august_1_2016

hier ist ein Code-Snippet von der Dokumentationsseite 

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();
    }
}
21
A.Alqadomi

Ich habe ein leeres FrameLayout erstellt, das im Layout über dem MapFragment angeordnet ist. Ich setze dann einen onTouchListener in dieser Ansicht, damit ich weiß, wann die Karte berührt wurde, aber false zurückgeben, damit die Berührung an die Karte weitergegeben wird.

<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
Flyview

Gaucho hat eine großartige Antwort, und als ich die vielen Verbesserungen sah, von denen ich dachte, dass sie vielleicht eine andere Implementierung brauchen:

Ich brauchte es, um einen Hörer zu verwenden damit ich auf die Berührung reagieren kann und nicht ständig prüfen muss.

Ich habe alles in einer Klasse zusammengefasst, die folgendermaßen verwendet werden kann:

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

wenn das Mapfragment vom Typ TouchSupportMapFragment sein muss und in der Layout-XML diese Zeile benötigt wird:

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

Hier ist die Klasse:

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);
        }
    }
}
6
Björn Kechel

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

Siehe diesen Link. Implementieren Sie die Schnittstelle, geben Sie die onMapClick()-Methode ein oder geben Sie die gewünschte Variable ein und setzen Sie die onMapClickListener auf die richtige Implementierung.

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
adarsh
  // 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
Pratibha Sarode

Für Mono Liebhaber:

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
Léon Pelletier

@Gaucho MySupportMapFragment wird offensichtlich von einem anderen Ergebnis oder einer anderen Aktivität verwendet (wobei möglicherweise mehr Ansichtselemente als das Kartenfragment vorhanden sind). Wie kann man dieses Ereignis dann an das nächste Fragment senden, in dem es verwendet werden soll. Müssen wir erneut ein Interface schreiben, um das zu tun?

0
user2201332

Ich habe eine einfachere Lösung, die sich von der TouchableWrapper unterscheidet, und dies funktioniert mit der letzten Version von play-services-maps:10.0.1. Diese Lösung verwendet nur die Kartenereignisse und verwendet keine benutzerdefinierten Ansichten. Verwendet keine veralteten Funktionen und wird wahrscheinlich mehrere Versionen unterstützen.

Zuerst benötigen Sie eine Flag-Variable, in der gespeichert wird, ob die Karte durch eine Animation oder eine Benutzereingabe verschoben wird (dies setzt voraus, dass jede Kamerabewegung, die nicht durch eine Animation ausgelöst wird, vom Benutzer ausgelöst wird).

GoogleMap googleMap;
boolean movedByApi = false;

Ihr Fragment oder Ihre Aktivität muss GoogleMap.OnMapReadyCallback, GoogleMap.CancelableCallback implementieren.

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

und dies zwingt Sie zur Implementierung der Methoden onMapReady, onFinish, onCancel. Das googleMap-Objekt in onMapReady muss einen Eventlistener für die Kamerabewegung festlegen

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

Und schließlich ist es besser, wenn Sie eine generische Funktion zum Verschieben der Karte erstellen

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

oder einfach jedes Mal, wenn Sie die Karte verschieben, aktivieren Sie die Flagge vor der Animation

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

Ich hoffe das hilft!

0
Sander Rito