我無法找到關於如何攔截新版Google地圖API v2上的地圖觸摸的示例。谷歌地圖Android API v2 - 在地圖上檢測觸摸
我需要知道用戶何時觸摸地圖才能停止線程(圍繞我當前位置的地圖中心)。
我無法找到關於如何攔截新版Google地圖API v2上的地圖觸摸的示例。谷歌地圖Android API v2 - 在地圖上檢測觸摸
我需要知道用戶何時觸摸地圖才能停止線程(圍繞我當前位置的地圖中心)。
@ape這裏就如何截取地圖點擊寫一個答案,但我需要攔截觸摸,然後他建議在它的答案,How to handle onTouch event for map in Google Map API v2?的評論下面的鏈接。
該解決方案似乎是一種可能的解決方法,但建議的代碼不完整。出於這個原因,我重寫並測試了它,現在它可以工作。
這是工作代碼:
我創建的類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;
}
}
我甚至創建的類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);
}
}
在我宣佈佈局它這樣:
<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"
/>
就在我只寫了主要業務測試以下:
public class MainActivity extends FragmentActivity {
public static boolean mMapIsTouched = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
優秀的完成你所包含的鏈接 – aez
投了票,因爲這不是用戶需要的,但這就是他所要求的。這就是我所需要的:) –
@Gaucho,我不得不改進一點該解決方案,主要是通過使用自定義監聽器而不是使用公共靜態變量。查看下面的解決方案。 –
請參閱此鏈接。實施接口並填寫onMapClick()
方法或您需要的任何一種,並將onMapClickListener
設置爲正確的實施方式。
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
}
}
非常感謝ndsmyter提供的答案。 onMapClick在地圖上點擊時截獲,但當您在地圖上移動手指時,它不起作用。我不僅需要攔截地圖點擊,還要攔截地圖平移。你知道該怎麼辦? – Gaucho
檢查文檔..這不是你的點擊事件 – adarsh
地圖觸摸不是「地圖點擊」,所以這個問題沒有回答。我需要攔截由於用戶在地圖上的觸摸而導致的地圖移動,並且我無法找到攔截此操作的工作方式。我認爲我無法使用setOnCameraChangeListener,因爲我仍然使用animateCamera方法更新代碼中的相機位置,然後我只需要一個偵聽器在地圖平移過程中攔截地圖上的觸摸。 – Gaucho
對於Mono愛好者:
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);
}
}
}
這裏有一個簡單的解決方案根據用戶的選擇來獲得位置(點擊地圖選項)
googleMap.setOnMapClickListener(new OnMapClickListener() {
@Override
public void onMapClick(LatLng arg0) {
// TODO Auto-generated method stub
Log.d("arg0", arg0.latitude + "-" + arg0.longitude);
}
});
我在佈局中的MapFragment頂部創建了一個空的FrameLayout。然後我在這個視圖上設置一個onTouchListener,所以我知道地圖何時被觸摸,但返回false,以便觸摸傳遞到地圖上。
<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.
}
});
這根本行不通。在ACTION_DOWN上返回false將導致ACTION_UP被中斷,並且不會爲其調用onTouch。 –
// 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
}
}
});
@Gaucho MySupportMapFragment顯然將通過一些其它fargment或活性(其中可能有更多的視圖元素比地圖片段)一起使用。那麼如何將這個事件派發到下一個將被使用的片段。我們是否需要重新編寫一個界面來做到這一點?
高科有很大的答案,看到許多upvotes我想可能有一些需要另一種實現方式:
我需要它使用監聽這樣我就可以在觸摸反應,並沒有不斷檢查它。
我把所有能像這樣使用一個類:
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
}
}
});
其中mapfragment必須類型TouchSupportMapFragment,並在佈局XML需要該行:
<fragment class="de.bjornson.maps.TouchSupportMapFragment"
...
這裏是這個類:
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);
}
}
}
此功能和更多現在支持:)
這是開發人員注意事項(問題4636):
在2016年8月發佈引入了一組新的相機變化的聽衆中的攝像機運動的開始,持續和結束事件。您還可以瞭解相機爲何在移動,無論是由用戶手勢,內置API動畫還是由開發人員控制的移動。有關詳細信息,請參閱指南相機改變事件: https://developers.google.com/maps/documentation/android-api/events#camera-change-events
另外,請參見發行說明: https://developers.google.com/maps/documentation/android-api/releases#august_1_2016
這裏是從文檔頁面的代碼片段
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();
}
}
我有一個更簡單的解決方案與TouchableWrapper
不同,它適用於play-services-maps:10.0.1
的最新版本。此解決方案僅使用地圖事件並且不使用自定義視圖。不使用已棄用的功能,並可能支持多個版本。
首先,你需要(asumes即不是由動畫都會觸發攝像機移動是由用戶觸發該代碼)
GoogleMap googleMap;
boolean movedByApi = false;
存儲如果地圖是由動畫或通過用戶輸入移動的標誌變量
你fragament或活動必須實現GoogleMap.OnMapReadyCallback
,GoogleMap.CancelableCallback
public class ActivityMap extends Activity implements OnMapReadyCallback, GoogleMap.CancelableCallback{
...
}
,這迫使你實現方法onMapReady
,onFinish
,onCancel
。而在onMapReady
GoogleMap對象必須設置一個事件偵聽相機移動
@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;
}
最後它的尤爲明顯,如果你創建移動您移動地圖的地圖
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);
}
或只是每次的通用功能,在動畫之前激活標誌
movedByApi = true;
googleMap.animateCamera(cu, this);
我希望這有助於!
如果用戶在動畫中觸摸地圖,這不起作用。 –
如果有人回答您的問題,請將您的問題標記爲已回答。此外,你明確地說'在地圖上點擊',所以不需要在ape或CommonsWare中捕捉不能讀懂你的想法。 – Maarten
我甚至可以將它標記爲已回答,但我寫了「地圖觸摸」,而不是「單擊」地圖。評論中的@ape提示瞭解決我的問題的另一個線程(http:// stackoverflow。com/questions/13722869/how-to-handle-ontouch-event-for-map-in-google-map-api-v2),但我無法使用它,因爲我在評論中寫道。我無法在鏈接上的線程上獲得解決方案。我應該打開另一個問題嗎? – Gaucho
你的答案應該是一個答案,而不是編輯成問題。你已經很難遵循。如果你自己的答案是最能幫助你的答案,那麼你甚至可以接受它來向其他人展示。 –