我该如何处理使用谷歌地图Android版V2移动地图结束了吗?(How can I handle m

2019-06-21 13:25发布

我想尽快地图中心已更改地址解析地址。

我该如何处理映射moveend新的谷歌地图Android版V2? (我说的是这样,那么用户通过手指拖动地图)

Answer 1:

下面是确定拖曳开始和结束拖动事件可能的解决方法:

你必须扩展SupportMapFragment或MapFragment。 在onCreateView你要包装你的MapView在自定义的FrameLayout(例如下面这是类“TouchableWrapper”),在其中截取的触摸事件,并确认地图是否被窃听或没有。 如果你的“onCameraChange”被调用,只需查地图视图是否被按下(例如下面这个是变量“mMapIsTouched”)。

示例代码:

更新1:

  • 在getView返回原始创建的视图()
  • 使用dispatchTouchEvent()代替onInterceptTouchEvent()

定制的FrameLayout:

private class TouchableWrapper extends FrameLayout {

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mMapIsTouched = true;
                break;
            case MotionEvent.ACTION_UP:
                mMapIsTouched = false;
                break;
        }

        return super.dispatchTouchEvent(ev);

    }

}

在您的自定义MapFragment:

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

在你的相机更改回调方法:

private final OnCameraChangeListener mOnCameraChangeListener = 
        new OnCameraChangeListener() {

    @Override
    public void onCameraChange(CameraPosition cameraPosition) {
        if (!mMapIsTouched) {
            refreshClustering(false);
        }
    }
};


Answer 2:

看看新的地图API。

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

developers.google.com样本



Answer 3:

过时的使用新的地图API来代替。 请参阅从punksta答案。

使用AZ13的解决方案之上,并跑入在评论中提到的问题后,我创建了以下解决方案,即更可靠地解决了这个问题。 然而,由于我使用的是定时器onRelease事件后,确定地图是否仍然动画,还有在此解决方案稍有延迟。

:该代码可在Github上通过此链接找到https://github.com/MadsFrandsen/MapStateListener

我的解决方案可以通过以下方式的活动中使用:

new MapStateListener(mMap, mMapFragment, this) {
  @Override
  public void onMapTouched() {
    // Map touched
  }

  @Override
  public void onMapReleased() {
    // Map released
  }

  @Override
  public void onMapUnsettled() {
    // Map unsettled
  }

  @Override
  public void onMapSettled() {
    // Map settled
  }
};


Answer 4:

我会尝试onCameraChangeListener 。 监听器被称为每当摄像机的动作完成的时间。 听者也会给你新的位置。 在我的测试监听器也许拖着有一个更好的解决方案中相当经常被调用。



Answer 5:

与播放服务,地图开始9.4.0可以简单地使用GoogleMap.OnCameraMoveStartedListenerGoogleMap.OnCameraMoveListenerGoogleMap.OnCameraIdleListener

如果由于某种原因,你要使用旧的API,它现在不建议你可以使用onCameraChangeListener 。 但是,你必须要知道的两件事情:

  1. onCameraChange()同时拖动地图或仅一次可能会被调用多次(拖动停止时)。
  2. 在最后一次通话的摄像头位置onCameraChange()可以从最终摄影机位置略有不同。

下面的代码利用了这两个问题考虑在内:

private static final int MESSAGE_ID_SAVE_CAMERA_POSITION = 1;
private static final int MESSAGE_ID_READ_CAMERA_POSITION = 2;
private CameraPosition lastCameraPosition;
private Handler handler;
private GoogleMap googleMap;

public void onMapReady(GoogleMap theGoogleMap) {
    googleMap = theGoogleMap;

    handler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == MESSAGE_ID_SAVE_CAMERA_POSITION) {
                lastCameraPosition = googleMap.getCameraPosition();
            } else if (msg.what == MESSAGE_ID_READ_CAMERA_POSITION) {
                if (lastCameraPosition.equals(googleMap.getCameraPosition())) {
                    Log.d(LOG, "Camera position stable");
                }
            }
        }
    };

    googleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
        @Override
        public void onCameraChange(CameraPosition cameraPosition) {
            handler.removeMessages(MESSAGE_ID_SAVE_CAMERA_POSITION);
            handler.removeMessages(MESSAGE_ID_READ_CAMERA_POSITION);
            handler.sendEmptyMessageDelayed(MESSAGE_ID_SAVE_CAMERA_POSITION, 300);
            handler.sendEmptyMessageDelayed(MESSAGE_ID_READ_CAMERA_POSITION, 600);
        }
    });
}


Answer 6:

@Override
public boolean onTouchEvent(MotionEvent event, MapView mapView){

    if(event.getAction() == MotionEvent.ACTION_MOVE)
        return true;

    return false;
}


Answer 7:

我有我的动画标记只要用户拖动地图中心。 我一直在使用斯塔斯Shakirov答案实现了它

MapDragListenerFragment.class

public class MapDragListenerFragment extends Fragment implements OnMapReadyCallback, GoogleMap.OnMapLoadedCallback {

    private Context mContext;
    private SupportMapFragment supportMapFragment;
    private Marker centerMarker;
    private LatLng mapCenterLatLng;
    private TextView tvLocationName;
    private Button btnFinalizeDestination;
    private GoogleMap mGoogleMap;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_map_drag_listener, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mContext = getActivity();

        tvLocationName = (TextView) view.findViewById(R.id.tv_location_name);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        FragmentManager fm = getActivity().getSupportFragmentManager();//getChildFragmentManager();//
        supportMapFragment = (SupportMapFragment) fm.findFragmentById(R.id.map_container);
        if (supportMapFragment == null) {
            //// FIXME: 2/13/2017 crashes at casting to TouchableMapFragment
            supportMapFragment = SupportMapFragment.newInstance();
            fm.beginTransaction().replace(R.id.map_container, supportMapFragment).commit();
        }
        supportMapFragment.getMapAsync(this);

    }

    @Override
    public void onMapReady(GoogleMap googleMap) {

        if (googleMap != null) {
            mGoogleMap = googleMap;

            centerMarker = mGoogleMap.addMarker(new MarkerOptions().position(mGoogleMap.getCameraPosition().target)
                    .title("Center of Map")
                    .icon(BitmapDescriptorFactory.fromResource(R.drawable.end_green)));

            mGoogleMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
                @Override
                public void onCameraIdle() {
                    mapCenterLatLng = mGoogleMap.getCameraPosition().target;

                    animateMarker(centerMarker,mapCenterLatLng,false);

                    Toast.makeText(mContext, "The camera has stopped moving.",
                            Toast.LENGTH_SHORT).show();

                    String address = getCompleteAddressString(mapCenterLatLng.longitude,mapCenterLatLng.longitude);
                    tvLocationName.setText(address);
                }
            });
            mGoogleMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
                @Override
                public void onCameraMoveStarted(int reason) {
                    if (reason == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE) {
                        ///tvLocationName.setText("Lat " + mapCenterLatLng.latitude + "  Long :" + mapCenterLatLng.longitude);
                        Toast.makeText(mContext, "The user gestured on the map.",
                                Toast.LENGTH_SHORT).show();
                    } else if (reason == GoogleMap.OnCameraMoveStartedListener
                            .REASON_API_ANIMATION) {
                        Toast.makeText(mContext, "The user tapped something on the map.",
                                Toast.LENGTH_SHORT).show();
                    } else if (reason == GoogleMap.OnCameraMoveStartedListener
                            .REASON_DEVELOPER_ANIMATION) {
                        Toast.makeText(mContext, "The app moved the camera.",
                                Toast.LENGTH_SHORT).show();
                    }
                }
            });
            mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
                @Override
                public void onCameraMove() {
                    Toast.makeText(mContext, "The camera is moving.",
                            Toast.LENGTH_SHORT).show();
                }
            });
            mGoogleMap.setOnCameraMoveCanceledListener(new GoogleMap.OnCameraMoveCanceledListener() {
                @Override
                public void onCameraMoveCanceled() {
                    Toast.makeText(mContext, "Camera movement canceled.",
                            Toast.LENGTH_SHORT).show();
                }
            });

            mapCenterLatLng = mGoogleMap.getCameraPosition().target;// it should be done on MapLoaded.

            if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) !=
                    PackageManager.PERMISSION_GRANTED &&
                    ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) !=
                            PackageManager.PERMISSION_GRANTED) {
                return;
            }
            mGoogleMap.setMyLocationEnabled(true);
            mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(15));

            mGoogleMap.setOnMapLoadedCallback(this);
            mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
                @Override
                public void onCameraMove() {

                }
            });
        }
    }

    public void animateMarker(final Marker marker, final LatLng toPosition,
                              final boolean hideMarker) {
        final Handler handler = new Handler();
        final long start = SystemClock.uptimeMillis();
        Projection proj = mGoogleMap.getProjection();
        Point startPoint = proj.toScreenLocation(marker.getPosition());
        final LatLng startLatLng = proj.fromScreenLocation(startPoint);
         final long duration = 500;
        final Interpolator interpolator = new LinearInterpolator();
        handler.post(new Runnable() {
            @Override
            public void run() {
                long elapsed = SystemClock.uptimeMillis() - start;
                float t = interpolator.getInterpolation((float) elapsed
                        / duration);
                double lng = t * toPosition.longitude + (1 - t)
                        * startLatLng.longitude;
                double lat = t * toPosition.latitude + (1 - t)
                        * startLatLng.latitude;
                marker.setPosition(new LatLng(lat, lng));
                if (t < 1.0) {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16);
                } else {
                    if (hideMarker) {
                        marker.setVisible(false);
                    } else {
                        marker.setVisible(true);
                    }
                }
            }
        });
    }
}

其中fragment_map_drag_listener.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <fragment
            android:id="@+id/map_container"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <ImageView
            android:id="@+id/iv_center_overlay"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:visibility="gone"
            android:layout_centerInParent="true"
            android:src="@drawable/start_blue" />
    </RelativeLayout>


    <TextView
        android:id="@+id/tv_location_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="4dp"
        android:text="Location Name" />
</LinearLayout>

其中MapDragListenerActivity

public class MapDragListenerActivity extends AppCompatActivity {

    private Context mContext;
    private static final String TAG = MapDragListenerFragment.class.getSimpleName();
    private MapDragListenerFragment mapDragListenerFragment;

    private Button selectPlaceBtn;
    public static final int PLACE_AUTOCOMPLETE_REQUEST_CODE = 1219;

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

        mContext = MapDragListenerActivity.this;

        mapDragListenerFragment = new MapDragListenerFragment();
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.frame_container,//where frame_container is a FrameLayout
                        mapDragListenerFragment,
                        MapyFragment.class.getSimpleName()).commit();


        selectPlaceBtn = (Button) findViewById(R.id.btn_select_place);

        selectPlaceBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    Intent intent = new PlaceAutocomplete.IntentBuilder(
                            PlaceAutocomplete.MODE_FULLSCREEN).build(MapDragListenerActivity.this);
                    startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE);
                } catch (GooglePlayServicesRepairableException e) {
                    e.printStackTrace();
                } catch (GooglePlayServicesNotAvailableException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if(requestCode == PLACE_AUTOCOMPLETE_REQUEST_CODE){
            if (resultCode == RESULT_OK) {
                Place place = PlaceAutocomplete.getPlace(mContext, data);
                if(mapDragListenerFragment != null && mapDragListenerFragment.isVisible())
                    mapDragListenerFragment.updateMarkerAtPosition(
                            place.getLatLng() ,place.getName().toString());

                Log.i(TAG, "Place:" + place.toString());
            } else if (resultCode == PlaceAutocomplete.RESULT_ERROR) {
                Status status = PlaceAutocomplete.getStatus(mContext, data);
                Log.i(TAG, status.getStatusMessage());
            } else if (requestCode == RESULT_CANCELED) {

            }
        }
    }
}

activity_map_drag_listener.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_select_place"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Select Place" />

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

</LinearLayout>


Answer 8:

最简单的方法是使用setOnCameraIdleListener方法来处理你的地图片段触摸监听你的举动最终状态。 见下面的例子:

mMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
    @Override
    public void onCameraMoveStarted(int i) {
        mapPin.startAnimation(animZoomOut);
    }
});

mMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
    @Override
    public void onCameraIdle() {
        mapPin.startAnimation(animZoomIn);
    }
});


Answer 9:

我认为,在地图的onclick事件是:map.setOnMapClick ...但事件的阻力:map.onCameraChangeListener因为我所说的log.e在两个函数和它显示像的onClick观点和看法ondrag当 。 因此,只要使用它们。



Answer 10:

与Xamarin的Android,基于Tobus答案的处理器内部类增强型解决方案:

public void OnMapReady(GoogleMap googleMap)
{
        _googleMap = googleMap;

        if (_googleMap != null)
        {
            _cameraPositionHandler = new CameraPositionlHandler(_googleMap);

            _googleMap.CameraChange += OnCameraChanged; 

        }
}

void OnCameraChanged (object sender, GoogleMap.CameraChangeEventArgs e)
{   
    _cameraPositionHandler.RemoveMessages(MESSAGE_ID_SAVE_CAMERA_POSITION);
    _cameraPositionHandler.RemoveMessages(MESSAGE_ID_READ_CAMERA_POSITION);                 
    _cameraPositionHandler.SendEmptyMessageDelayed(MESSAGE_ID_SAVE_CAMERA_POSITION, 300);
    _cameraPositionHandler.SendEmptyMessageDelayed(MESSAGE_ID_READ_CAMERA_POSITION, 600);

}

用下面的内部类:

    private class CameraPositionlHandler :  Handler 
    {
        private CameraPosition _lastCameraPosition;
        private GoogleMap _googleMap;

        public CameraPositionlHandler (GoogleMap googleMap)
        {
            _googleMap = googleMap;
        }

        public override void HandleMessage(Message msg) 
        {
            if (_googleMap != null) 
            {
                if (msg.What == MESSAGE_ID_SAVE_CAMERA_POSITION) {
                    _lastCameraPosition = _googleMap.CameraPosition;
                } else if (msg.What == MESSAGE_ID_READ_CAMERA_POSITION) {
                    if (_lastCameraPosition.Equals(_googleMap.CameraPosition)) {
                        Console.WriteLine("Camera position stable");
                        //do what you want
                    }
                }
            }
        }
    }


Answer 11:

在相机闲置是你现在应该用什么

 googleMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
        @Override
        public void onCameraIdle() {
           //Called when camera movement has ended, there are no pending animations and the user has stopped interacting with the map.
        }
 });


文章来源: How can I handle map move end using Google Maps for Android V2?