Как я могу обработать перенос карты с помощью Google Maps для Android V2?

Я хочу указать адрес геокода, как только будет изменен центр карты.

Как я могу обрабатывать перемещение карты с помощью новых карт Google для Android V2? (Я говорю о случае, тогда пользователь перетаскивает карту пальцем)

Ниже приведено возможное обходное решение для определения начальных и конечных событий перетаскивания:

Вы должны расширить SupportMapFragment или MapFragment. В onCreateView вы должны обернуть свой MapView в настраиваемом FrameLayout (в примере ниже он является classом TouchableWrapper), в котором вы перехватываете события касания и узнаете, используется ли карта или нет. Если вы вызываете «onCameraChange», просто проверьте, нажато ли отображение карты или нет (в примере ниже это переменная «mMapIsTouched»).

Пример кода:

ОБНОВЛЕНИЕ 1:

  • return original created view в 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); } } }; 

Проверьте новые карты 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

OUTDATED Используйте вместо этого новый 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 } }; 

Я бы попробовал onCameraChangeListener . Слушатель вызывается каждый раз, когда движение камеры завершено. Слушатель также предоставит вам новое место. В моих тестах слушатель часто вызывался во время перетаскивания, может быть, есть лучшее решение.

Начиная с игровых сервисов-карт 9.4.0 вы можете просто использовать GoogleMap.OnCameraMoveStartedListener , GoogleMap.OnCameraMoveListener и GoogleMap.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); } }); } 
 @Override public boolean onTouchEvent(MotionEvent event, MapView mapView){ if(event.getAction() == MotionEvent.ACTION_MOVE) return true; return false; } 

Я должен оживить мой маркер до центра, пока пользователь перетаскивает карту. Я внедрил его, используя ответ Стаса Шакирова

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

         

где 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

      

Самый простой способ – использовать метод setOnCameraIdleListener для обработки состояния конечного состояния прослушивания касания на fragmentе карты. см. пример ниже:

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

Я думаю, что событие onclick на карте: map.setOnMapClick … Но drag and drop события : map.onCameraChangeListener, потому что я вызываю log.e в обеих этих функциях, и он отображается как вид onClick и onDrag . Поэтому просто используйте их для вас.

Расширенное решение с внутренним classом Handler в 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); } 

Со следующим внутренним classом:

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

На холостом ходу вы должны использовать сейчас

  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. } }); 
  • Преобразование изображения в PDF в Android
  • Как выполнить поисковый запрос с Firebase с помощью Android FirebaseUI
  • Сначала вызовите removeView () родителя ребенка
  • Ошибка поддержки библиотеки Android после обновления до 23.3.0
  • Как сохранить соотношение сторон на кнопках изображения в андроиде?
  • Как получить URL из хранилища Firebase getDownloadURL
  • Что отличает MainActivity.this от getApplicationContext ()
  • Android - LinearLayout Горизонтальная с обертыванием детей
  • Как отключить изменение ориентации на Android?
  • Как получить исходный код HTML из url в android?
  • android: определение типа безопасности беспроводных сетей в диапазоне (без подключения к ним)
  • Давайте будем гением компьютера.