بااستفاده از کیت توسعه نرمافزار Google Maps برای Android، میتوانید به رویدادهای روی نقشه گوش دهید.
نمونههای کد
مخزن ApiDemos در GitHub شامل نمونههایی است که رویدادها و شنوندگان را نشان میدهد:
Kotlin
- EventsDemoActivity: رویدادهای کلیک روی نقشه و تغییر دوربین
- CameraDemoActivity: رویدادهای تغییر دوربین
- CircleDemoActivity: رویدادهای کلیک و کشیدن نشانگر
- GroundOverlayDemoActivity: رویدادهای کلیک رونهاد زمین
- IndoorDemoActivity: رویدادهای نقشه داخلی
- MarkerDemoActivity: رویدادهای نشانگر و پنجره اطلاعات
- PolygonDemoActivity: رویدادهای چندضلعی
جاوا
- EventsDemoActivity: رویدادهای کلیک روی نقشه و تغییر دوربین
- CameraDemoActivity: رویدادهای تغییر دوربین
- CircleDemoActivity: رویدادهای کلیک و کشیدن نشانگر
- GroundOverlayDemoActivity: رویدادهای کلیک رونهاد زمین
- IndoorDemoActivity: رویدادهای نقشه داخلی
- MarkerDemoActivity: رویدادهای نشانگر و پنجره اطلاعات
- PolygonDemoActivity: رویدادهای چندضلعی
رویدادهای کلیک روی نقشه / کلیک طولانی
اگر میخواهید به کاربری که روی نقطهای در نقشه تکضرب میزند پاسخ دهید، میتوانید از
OnMapClickListener استفاده کنید که میتوانید آن را با
فراخوانی GoogleMap.setOnMapClickListener(OnMapClickListener) در نقشه تنظیم کنید. وقتی کاربر
جایی روی نقشه کلیک میکند (تکضرب میزند)، رویداد onMapClick(LatLng) را دریافت خواهید کرد
که نشاندهنده مکانی روی نقشه است که کاربر کلیک کرده است. توجه داشته باشید که
اگر به مکان مربوطه در صفحهنمایش (برحسب پیکسل) نیاز دارید، میتوانید
Projection را از نقشه دریافت کنید که به شما امکان میدهد
بین مختصات عرض/طول جغرافیایی و مختصات پیکسل صفحهنمایش تبدیل کنید.
همچنین میتوانید بااستفاده از
OnMapLongClickListener که میتوانید با فراخوانی GoogleMap.setOnMapLongClickListener(OnMapLongClickListener) روی نقشه تنظیم کنید،
به رویدادهای کلیک طولانی گوش دهید.
این شنونده رفتاری مشابه شنونده کلیک دارد و در رویدادهای کلیک طولانی با یک فراخوانی برگشتی onMapLongClick(LatLng) مطلع خواهد شد.
غیرفعال کردن رویدادهای کلیک در حالت سادهشده
برای غیرفعال کردن رویدادهای کلیک روی نقشه در حالت ساده، setClickable()
را در نمای حاوی MapView یا MapFragment فراخوانی کنید. این ویژگی مفید است،
برای مثال، هنگام نمایش نقشه یا نقشهها در نمای فهرست، جایی که میخواهید
رویداد کلیک کنشی را فراخوانی کند که به نقشه مربوط نیست.
گزینه غیرفعال کردن رویدادهای کلیک فقط در حالت ساده دردسترس است. غیرفعال کردن رویدادهای کلیک باعث میشود نشانگرها نیز غیرقابلکلیک شوند. این کار بر سایر کنترلهای روی نقشه تأثیری نخواهد گذاشت.
برای MapView:
Kotlin
mapView?.isClickable = false
جاوا
if (mapView != null) { mapView.setClickable(false); }
برای MapFragment:
Kotlin
if (context is FragmentActivity) { val mapFragment = context.supportFragmentManager .findFragmentById(R.id.map) as? SupportMapFragment val view = mapFragment?.view view?.isClickable = false }
جاوا
if (context instanceof FragmentActivity) { SupportMapFragment mapFragment = (SupportMapFragment) ((FragmentActivity) context) .getSupportFragmentManager().findFragmentById(R.id.map); if (mapFragment != null) { View view = mapFragment.getView(); if (view != null) { view.setClickable(false); } } }
رویدادهای تغییر دوربین
نمای نقشه بهعنوان دوربینی مدلسازی شده است که به صفحهای تخت نگاه میکند. میتوانید ویژگیهای دوربین را تغییر دهید تا بر سطح بزرگنمایی، درگاه مشاهده، و چشمانداز نقشه تأثیر بگذارد. راهنمای دوربین را ببینید. کاربران همچنین میتوانند با انجام اشارهها روی دوربین تأثیر بگذارند.
بااستفاده از شنوندگان تغییر دوربین، میتوانید حرکات دوربین را پیگیری کنید. برنامه شما میتواند اعلانهای مربوط به شروع، ادامه، و پایان رویدادهای حرکت دوربین را دریافت کند. همچنین میتوانید ببینید دوربین چرا حرکت میکند، آیا این حرکت ناشی از اشارههای کاربر، پویانماییهای API داخلی، یا حرکات کنترلشده توسط توسعهدهنده است.
نمونه زیر همه شنوندگان رویداد دوربین دردسترس را نشان میدهد:
Kotlin
/* * Copyright 2018 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.kotlindemos import com.example.common_ui.catalog.Sample import com.example.common_ui.catalog.Complexity import com.example.common_ui.catalog.Framework import android.graphics.Color import android.os.Bundle import android.util.Log import android.view.View import android.widget.CompoundButton import android.widget.SeekBar import android.widget.Toast import com.example.common_ui.R import com.google.android.gms.maps.CameraUpdate import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.GoogleMap.CancelableCallback import com.google.android.gms.maps.GoogleMap.OnCameraIdleListener import com.google.android.gms.maps.GoogleMap.OnCameraMoveCanceledListener import com.google.android.gms.maps.GoogleMap.OnCameraMoveListener import com.google.android.gms.maps.GoogleMap.OnCameraMoveStartedListener import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment import com.google.android.gms.maps.model.CameraPosition import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.MarkerOptions import com.example.common_ui.databinding.CameraDemoBinding import com.google.android.gms.maps.model.PolylineOptions /** * This shows how to change the camera position for the map. */ @Sample( id = "com.example.kotlindemos.CameraDemoActivity", title = "Camera Controls & Animation", description = "Programmatic camera panning, zooming, tilt, bearing, and smooth animations.", category = "Camera Controls", complexity = Complexity.SIMPLE, tags = ["#camera", "#animation", "#bearing", "#tilt", "#zoom", "#pan"], apiCalls = [ "GoogleMap.animateCamera(CameraUpdate)", "GoogleMap.moveCamera(CameraUpdate)", "GoogleMap.addMarker(MarkerOptions)", "CameraUpdateFactory.newCameraPosition(CameraPosition)" ], purpose = "Demonstrates programmatic camera movements, animated transitions, tilt angles, and bearing rotations.", successCriteria = "Buttons animate camera smoothly with custom durations, stops, and rotation angles.", failureIndicators = "Jerky animations, unexpected camera jumps, or tilt angle exceeding platform constraints.", framework = Framework.KOTLIN_VIEWS ) class CameraDemoActivity : SamplesBaseActivity(), OnCameraMoveStartedListener, OnCameraMoveListener, OnCameraMoveCanceledListener, OnCameraIdleListener, OnMapReadyCallback { /** * The amount by which to scroll the camera. Note that this amount is in raw pixels, not dp * (density-independent pixels). */ private val SCROLL_BY_PX = 100 private val TAG = CameraDemoActivity::class.java.name private val sydneyLatLng = LatLng(-33.87365, 151.20689) private val bondiLocation: CameraPosition = CameraPosition.Builder() .target(LatLng(-33.891614, 151.276417)) .zoom(15.5f) .bearing(300f) .tilt(50f) .build() private val sydneyLocation: CameraPosition = CameraPosition.Builder(). target(LatLng(-33.87365, 151.20689)) .zoom(15.5f) .bearing(0f) .tilt(25f) .build() private lateinit var map: GoogleMap private lateinit var animateToggle: CompoundButton private lateinit var customDurationToggle: CompoundButton private lateinit var customDurationBar: SeekBar private var currPolylineOptions: PolylineOptions? = null private var isCanceled = false private lateinit var binding: CameraDemoBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = CameraDemoBinding.inflate(layoutInflater) setContentView(binding.root) animateToggle = binding.animate customDurationToggle = binding.durationToggle customDurationBar = binding.durationBar updateEnabledState() val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) applyInsets(binding.mapContainer) binding.bondi.setOnClickListener(this::onGoToBondi) binding.sydney.setOnClickListener(this::onGoToSydney) binding.stopAnimation.setOnClickListener(this::onStopAnimation) binding.animate.setOnClickListener(this::onToggleAnimate) binding.scrollLeft.setOnClickListener(this::onScrollLeft) binding.scrollUp.setOnClickListener(this::onScrollUp) binding.scrollDown.setOnClickListener(this::onScrollDown) binding.scrollRight.setOnClickListener(this::onScrollRight) binding.zoomIn.setOnClickListener(this::onZoomIn) binding.zoomOut.setOnClickListener(this::onZoomOut) binding.tiltMore.setOnClickListener(this::onTiltMore) binding.tiltLess.setOnClickListener(this::onTiltLess) binding.durationToggle.setOnClickListener(this::onToggleCustomDuration) } override fun onResume() { super.onResume() updateEnabledState() } override fun onMapReady(googleMap: GoogleMap) { map = googleMap // return early if the map was not initialised properly with(googleMap) { setOnCameraIdleListener(this@CameraDemoActivity) setOnCameraMoveStartedListener(this@CameraDemoActivity) setOnCameraMoveListener(this@CameraDemoActivity) setOnCameraMoveCanceledListener(this@CameraDemoActivity) // We will provide our own zoom controls. uiSettings.isZoomControlsEnabled = false uiSettings.isMyLocationButtonEnabled = true // Show Sydney moveCamera(CameraUpdateFactory.newLatLngZoom(sydneyLatLng, 10f)) addMarker(MarkerOptions().position(sydneyLatLng).title("Sydney")) addMarker(MarkerOptions().position(LatLng(-33.891614, 151.276417)).title("Bondi Beach")) } } /** * When the map is not ready the CameraUpdateFactory cannot be used. This should be used to wrap * all entry points that call methods on the Google Maps API. * * @param stuffToDo the code to be executed if the map is initialised */ private fun checkReadyThen(stuffToDo: () -> Unit) { if (!::map.isInitialized) { Toast.makeText(this, R.string.map_not_ready, Toast.LENGTH_SHORT).show() } else { stuffToDo() } } /** * Called when the Go To Bondi button is clicked. */ @Suppress("UNUSED_PARAMETER") fun onGoToBondi(view: View) { checkReadyThen { changeCamera(CameraUpdateFactory.newCameraPosition(bondiLocation)) } } /** * Called when the Animate To Sydney button is clicked. */ @Suppress("UNUSED_PARAMETER") fun onGoToSydney(view: View) { checkReadyThen { changeCamera(CameraUpdateFactory.newCameraPosition(sydneyLocation), object : CancelableCallback { override fun onFinish() { Toast.makeText(baseContext, "Animation to Sydney complete", Toast.LENGTH_SHORT).show() } override fun onCancel() { Toast.makeText(baseContext, "Animation to Sydney canceled", Toast.LENGTH_SHORT).show() } }) } } /** * Called when the stop button is clicked. */ @Suppress("UNUSED_PARAMETER") fun onStopAnimation(view: View) = checkReadyThen { map.stopAnimation() } /** * Called when the zoom in button (the one with the +) is clicked. */ @Suppress("UNUSED_PARAMETER") fun onZoomIn(view: View) = checkReadyThen { changeCamera(CameraUpdateFactory.zoomIn()) } /** * Called when the zoom out button (the one with the -) is clicked. */ @Suppress("UNUSED_PARAMETER") fun onZoomOut(view: View) = checkReadyThen { changeCamera(CameraUpdateFactory.zoomOut()) } /** * Called when the tilt more button (the one with the /) is clicked. */ @Suppress("UNUSED_PARAMETER") fun onTiltMore(view: View) { checkReadyThen { val newTilt = Math.min(map.cameraPosition.tilt + 10, 90F) val cameraPosition = CameraPosition.Builder(map.cameraPosition).tilt(newTilt).build() changeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)) } } /** * Called when the tilt less button (the one with the \) is clicked. */ @Suppress("UNUSED_PARAMETER") fun onTiltLess(view: View) { checkReadyThen { val newTilt = Math.max(map.cameraPosition.tilt - 10, 0F) val cameraPosition = CameraPosition.Builder(map.cameraPosition).tilt(newTilt).build() changeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)) } } /** * Called when the left arrow button is clicked. This causes the camera to move to the left */ @Suppress("UNUSED_PARAMETER") fun onScrollLeft(view: View) { checkReadyThen { changeCamera(CameraUpdateFactory.scrollBy((-SCROLL_BY_PX).toFloat(),0f)) } } /** * Called when the right arrow button is clicked. This causes the camera to move to the right. */ @Suppress("UNUSED_PARAMETER") fun onScrollRight(view: View) { checkReadyThen { changeCamera(CameraUpdateFactory.scrollBy(SCROLL_BY_PX.toFloat(), 0f)) } } /** * Called when the up arrow button is clicked. The causes the camera to move up. */ @Suppress("UNUSED_PARAMETER") fun onScrollUp(view: View) { checkReadyThen { changeCamera(CameraUpdateFactory.scrollBy(0f, (-SCROLL_BY_PX).toFloat())) } } /** * Called when the down arrow button is clicked. This causes the camera to move down. */ @Suppress("UNUSED_PARAMETER") fun onScrollDown(view: View) { checkReadyThen { changeCamera(CameraUpdateFactory.scrollBy(0f, SCROLL_BY_PX.toFloat())) } } /** * Called when the animate button is toggled */ @Suppress("UNUSED_PARAMETER") fun onToggleAnimate(view: View) = updateEnabledState() /** * Called when the custom duration checkbox is toggled */ @Suppress("UNUSED_PARAMETER") fun onToggleCustomDuration(view: View) = updateEnabledState() /** * Update the enabled state of the custom duration controls. */ private fun updateEnabledState() { customDurationToggle.isEnabled = animateToggle.isChecked customDurationBar.isEnabled = animateToggle.isChecked && customDurationToggle.isChecked } /** * Change the camera position by moving or animating the camera depending on the state of the * animate toggle button. */ private fun changeCamera(update: CameraUpdate, callback: CancelableCallback? = null) { if (animateToggle.isChecked) { if (customDurationToggle.isChecked) { // The duration must be strictly positive so we make it at least 1. map.animateCamera(update, Math.max(customDurationBar.progress, 1), callback) } else { map.animateCamera(update, callback) } } else { map.moveCamera(update) } } override fun onCameraMoveStarted(reason: Int) { if (!isCanceled) map.clear() var reasonText = "UNKNOWN_REASON" currPolylineOptions = PolylineOptions().width(5f) when (reason) { OnCameraMoveStartedListener.REASON_GESTURE -> { currPolylineOptions?.color(Color.BLUE) reasonText = "GESTURE" } OnCameraMoveStartedListener.REASON_API_ANIMATION -> { currPolylineOptions?.color(Color.RED) reasonText = "API_ANIMATION" } OnCameraMoveStartedListener.REASON_DEVELOPER_ANIMATION -> { currPolylineOptions?.color(Color.GREEN) reasonText = "DEVELOPER_ANIMATION" } } Log.d(TAG, "onCameraMoveStarted($reasonText)") addCameraTargetToPath() } /** * Ensures that currPolyLine options is not null before accessing it * * @param stuffToDo the code to be executed if currPolylineOptions is not null */ private fun checkPolylineThen(stuffToDo: () -> Unit) { if (currPolylineOptions != null) stuffToDo() } override fun onCameraMove() { Log.d(TAG, "onCameraMove") // When the camera is moving, add its target to the current path we'll draw on the map. checkPolylineThen { addCameraTargetToPath() } } override fun onCameraMoveCanceled() { // When the camera stops moving, add its target to the current path, and draw it on the map. checkPolylineThen { addCameraTargetToPath() map.addPolyline(currPolylineOptions!!) } isCanceled = true // Set to clear the map when dragging starts again. currPolylineOptions = null Log.d(TAG, "onCameraMoveCancelled") } override fun onCameraIdle() { checkPolylineThen { addCameraTargetToPath() map.addPolyline(currPolylineOptions!!) } currPolylineOptions = null isCanceled = false // Set to *not* clear the map when dragging starts again. Log.d(TAG, "onCameraIdle") } private fun addCameraTargetToPath() { currPolylineOptions?.add(map.cameraPosition.target) } }
جاوا
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.example.mapdemo; import com.example.common_ui.catalog.Sample; import com.example.common_ui.catalog.Complexity; import com.example.common_ui.catalog.Framework; import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.CompoundButton; import android.widget.SeekBar; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.google.android.gms.maps.CameraUpdate; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.CancelableCallback; import com.google.android.gms.maps.GoogleMap.OnCameraIdleListener; import com.google.android.gms.maps.GoogleMap.OnCameraMoveCanceledListener; import com.google.android.gms.maps.GoogleMap.OnCameraMoveListener; import com.google.android.gms.maps.GoogleMap.OnCameraMoveStartedListener; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; import com.example.common_ui.databinding.CameraDemoBinding; import com.google.android.gms.maps.model.PolylineOptions; /** * This shows how to change the camera position for the map. */ @Sample( id = "camera_demo", title = "Camera Controls & Animation", description = "Programmatic camera panning, zooming, tilt, bearing, and smooth animations.", category = "Camera Controls", complexity = Complexity.SIMPLE, tags = {"#camera", "#animation", "#bearing", "#tilt", "#zoom", "#pan"}, apiCalls = { "GoogleMap.animateCamera(CameraUpdate)", "GoogleMap.moveCamera(CameraUpdate)", "GoogleMap.addMarker(MarkerOptions)", "CameraUpdateFactory.newCameraPosition(CameraPosition)" }, purpose = "Demonstrates programmatic camera movements, animated transitions, tilt angles, and bearing rotations.", successCriteria = "Buttons animate camera smoothly with custom durations, stops, and rotation angles.", failureIndicators = "Jerky animations, unexpected camera jumps, or tilt angle exceeding platform constraints.", framework = Framework.JAVA_VIEWS ) public class CameraDemoActivity extends SamplesBaseActivity implements OnCameraMoveStartedListener, OnCameraMoveListener, OnCameraMoveCanceledListener, OnCameraIdleListener, OnMapReadyCallback { private static final String TAG = CameraDemoActivity.class.getName(); /** * The amount by which to scroll the camera. Note that this amount is in raw pixels, not dp * (density-independent pixels). */ private static final int SCROLL_BY_PX = 100; public static final CameraPosition BONDI = new CameraPosition.Builder().target(new LatLng(-33.891614, 151.276417)) .zoom(15.5f) .bearing(300) .tilt(50) .build(); public static final CameraPosition SYDNEY = new CameraPosition.Builder().target(new LatLng(-33.87365, 151.20689)) .zoom(15.5f) .bearing(0) .tilt(25) .build(); private GoogleMap map; private CompoundButton animateToggle; private CompoundButton customDurationToggle; private SeekBar customDurationBar; private PolylineOptions currPolylineOptions; private boolean isCanceled = false; private CameraDemoBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = CameraDemoBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); animateToggle = binding.animate; customDurationToggle = binding.durationToggle; customDurationBar = binding.durationBar; updateEnabledState(); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(com.example.common_ui.R.id.map); mapFragment.getMapAsync(this); applyInsets(binding.mapContainer); binding.bondi.setOnClickListener(this::onGoToBondi); binding.sydney.setOnClickListener(this::onGoToSydney); binding.stopAnimation.setOnClickListener(this::onStopAnimation); binding.animate.setOnClickListener(this::onToggleAnimate); binding.scrollLeft.setOnClickListener(this::onScrollLeft); binding.scrollUp.setOnClickListener(this::onScrollUp); binding.scrollDown.setOnClickListener(this::onScrollDown); binding.scrollRight.setOnClickListener(this::onScrollRight); binding.zoomIn.setOnClickListener(this::onZoomIn); binding.zoomOut.setOnClickListener(this::onZoomOut); binding.tiltMore.setOnClickListener(this::onTiltMore); binding.tiltLess.setOnClickListener(this::onTiltLess); binding.durationToggle.setOnClickListener(this::onToggleCustomDuration); } @Override protected void onResume() { super.onResume(); updateEnabledState(); } @Override public void onMapReady(GoogleMap googleMap) { map = googleMap; map.setOnCameraIdleListener(this); map.setOnCameraMoveStartedListener(this); map.setOnCameraMoveListener(this); map.setOnCameraMoveCanceledListener(this); // We will provide our own zoom controls. map.getUiSettings().setZoomControlsEnabled(false); map.getUiSettings().setMyLocationButtonEnabled(true); // Show Sydney LatLng sydneyLatLng = new LatLng(-33.87365, 151.20689); LatLng bondiLatLng = new LatLng(-33.891614, 151.276417); map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydneyLatLng, 10)); map.addMarker(new MarkerOptions().position(sydneyLatLng).title("Sydney")); map.addMarker(new MarkerOptions().position(bondiLatLng).title("Bondi Beach")); } public GoogleMap getMap() { return map; } /** * When the map is not ready the CameraUpdateFactory cannot be used. This should be called on * all entry points that call methods on the Google Maps API. */ private boolean checkReady() { if (map == null) { Toast.makeText(this, com.example.common_ui.R.string.map_not_ready, Toast.LENGTH_SHORT).show(); return false; } return true; } /** * Called when the Go To Bondi button is clicked. */ public void onGoToBondi(View view) { if (!checkReady()) { return; } changeCamera(CameraUpdateFactory.newCameraPosition(BONDI)); } /** * Called when the Animate To Sydney button is clicked. */ public void onGoToSydney(View view) { if (!checkReady()) { return; } changeCamera(CameraUpdateFactory.newCameraPosition(SYDNEY), new CancelableCallback() { @Override public void onFinish() { Toast.makeText(getBaseContext(), "Animation to Sydney complete", Toast.LENGTH_SHORT) .show(); } @Override public void onCancel() { Toast.makeText(getBaseContext(), "Animation to Sydney canceled", Toast.LENGTH_SHORT) .show(); } }); } /** * Called when the stop button is clicked. */ public void onStopAnimation(View view) { if (!checkReady()) { return; } map.stopAnimation(); } /** * Called when the zoom in button (the one with the +) is clicked. */ public void onZoomIn(View view) { if (!checkReady()) { return; } changeCamera(CameraUpdateFactory.zoomIn()); } /** * Called when the zoom out button (the one with the -) is clicked. */ public void onZoomOut(View view) { if (!checkReady()) { return; } changeCamera(CameraUpdateFactory.zoomOut()); } /** * Called when the tilt more button (the one with the /) is clicked. */ public void onTiltMore(View view) { if (!checkReady()) { return; } CameraPosition currentCameraPosition = map.getCameraPosition(); float currentTilt = currentCameraPosition.tilt; float newTilt = currentTilt + 10; newTilt = (newTilt > 90) ? 90 : newTilt; CameraPosition cameraPosition = new CameraPosition.Builder(currentCameraPosition) .tilt(newTilt).build(); changeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); } /** * Called when the tilt less button (the one with the \) is clicked. */ public void onTiltLess(View view) { if (!checkReady()) { return; } CameraPosition currentCameraPosition = map.getCameraPosition(); float currentTilt = currentCameraPosition.tilt; float newTilt = currentTilt - 10; newTilt = (newTilt > 0) ? newTilt : 0; CameraPosition cameraPosition = new CameraPosition.Builder(currentCameraPosition) .tilt(newTilt).build(); changeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); } /** * Called when the left arrow button is clicked. This causes the camera to move to the left */ public void onScrollLeft(View view) { if (!checkReady()) { return; } changeCamera(CameraUpdateFactory.scrollBy(-SCROLL_BY_PX, 0)); } /** * Called when the right arrow button is clicked. This causes the camera to move to the right. */ public void onScrollRight(View view) { if (!checkReady()) { return; } changeCamera(CameraUpdateFactory.scrollBy(SCROLL_BY_PX, 0)); } /** * Called when the up arrow button is clicked. The causes the camera to move up. */ public void onScrollUp(View view) { if (!checkReady()) { return; } changeCamera(CameraUpdateFactory.scrollBy(0, -SCROLL_BY_PX)); } /** * Called when the down arrow button is clicked. This causes the camera to move down. */ public void onScrollDown(View view) { if (!checkReady()) { return; } changeCamera(CameraUpdateFactory.scrollBy(0, SCROLL_BY_PX)); } /** * Called when the animate button is toggled */ public void onToggleAnimate(View view) { updateEnabledState(); } /** * Called when the custom duration checkbox is toggled */ public void onToggleCustomDuration(View view) { updateEnabledState(); } /** * Update the enabled state of the custom duration controls. */ private void updateEnabledState() { customDurationToggle.setEnabled(animateToggle.isChecked()); customDurationBar .setEnabled(animateToggle.isChecked() && customDurationToggle.isChecked()); } private void changeCamera(CameraUpdate update) { changeCamera(update, null); } /** * Change the camera position by moving or animating the camera depending on the state of the * animate toggle button. */ private void changeCamera(CameraUpdate update, CancelableCallback callback) { if (animateToggle.isChecked()) { if (customDurationToggle.isChecked()) { int duration = customDurationBar.getProgress(); // The duration must be strictly positive so we make it at least 1. map.animateCamera(update, Math.max(duration, 1), callback); } else { map.animateCamera(update, callback); } } else { map.moveCamera(update); } } @Override public void onCameraMoveStarted(int reason) { if (!isCanceled) { map.clear(); } String reasonText = "UNKNOWN_REASON"; currPolylineOptions = new PolylineOptions().width(5); switch (reason) { case OnCameraMoveStartedListener.REASON_GESTURE: currPolylineOptions.color(Color.BLUE); reasonText = "GESTURE"; break; case OnCameraMoveStartedListener.REASON_API_ANIMATION: currPolylineOptions.color(Color.RED); reasonText = "API_ANIMATION"; break; case OnCameraMoveStartedListener.REASON_DEVELOPER_ANIMATION: currPolylineOptions.color(Color.GREEN); reasonText = "DEVELOPER_ANIMATION"; break; } Log.d(TAG, "onCameraMoveStarted(" + reasonText + ")"); addCameraTargetToPath(); } @Override public void onCameraMove() { // When the camera is moving, add its target to the current path we'll draw on the map. if (currPolylineOptions != null) { addCameraTargetToPath(); } Log.d(TAG, "onCameraMove"); } @Override public void onCameraMoveCanceled() { // When the camera stops moving, add its target to the current path, and draw it on the map. if (currPolylineOptions != null) { addCameraTargetToPath(); map.addPolyline(currPolylineOptions); } isCanceled = true; // Set to clear the map when dragging starts again. currPolylineOptions = null; Log.d(TAG, "onCameraMoveCancelled"); } @Override public void onCameraIdle() { if (currPolylineOptions != null) { addCameraTargetToPath(); map.addPolyline(currPolylineOptions); } currPolylineOptions = null; isCanceled = false; // Set to *not* clear the map when dragging starts again. Log.d(TAG, "onCameraIdle"); } private void addCameraTargetToPath() { LatLng target = map.getCameraPosition().target; currPolylineOptions.add(target); } }
شنوندگان دوربین زیر دردسترس هستند:
وقتی دوربین شروع به حرکت میکند، فراخوانی برگشتی
onCameraMoveStarted()مربوط بهOnCameraMoveStartedListenerفراخوانده میشود. روش callback یکreasonبرای حرکت دوربین دریافت میکند. دلیل آن میتواند یکی از موارد زیر باشد:REASON_GESTUREنشان میدهد که دوربین در پاسخ به اشاره کاربر روی نقشه حرکت کرده است، مانند حرکت افقی، کج کردن، نیشگون گرفتن برای بزرگنمایی، یا چرخاندن نقشه.REASON_API_ANIMATIONنشان میدهد که API دوربین را در پاسخ به کنش غیرحرکتی کاربر، مانند تکضرب زدن روی دکمه بزرگنمایی، تکضرب زدن روی دکمه «مکان من»، یا کلیک کردن روی نشانگر، حرکت داده است.REASON_DEVELOPER_ANIMATIONنشان میدهد که برنامهتان حرکت دوربین را آغاز کرده است.
وقتی دوربین درحال حرکت است یا کاربر با صفحهنمایش لمسی تعامل دارد،
onCameraMove()فراخوانی برگشتیOnCameraMoveListenerچندین بار فراخوانده میشود. بهعنوان راهنمایی برای اینکه فراخوان برگشتی چند بار فراخوانده میشود، مفید است بدانید که API فراخوان برگشتی را یکبار در هر قاب فرا میخواند. بااینحال، توجه داشته باشید که این فراخوانی برگشتی بهصورت ناهمگام فراخوانی میشود و بنابراین با آنچه در صفحه قابلمشاهده است همگامسازی نمیشود. همچنین توجه داشته باشید که ممکن است موقعیت دوربین بین یکonCameraMove()تماس برگشتی و تماس بعدی تغییر نکند.وقتی دوربین از حرکت میایستد و کاربر تعامل با نقشه را متوقف میکند، فراخوانی برگشتی
OnCameraIdle()مربوط بهOnCameraIdleListenerفراخوانده میشود.وقتی حرکت فعلی دوربین قطع شود،
OnCameraMoveCanceled()فراخوانی برگشتیOnCameraMoveCanceledListenerفراخوانده میشود. بلافاصله پساز فراخوانی برگشتیOnCameraMoveCanceled()، فراخوانی برگشتیonCameraMoveStarted()باreasonجدید فراخوانده میشود.اگر برنامه شما بهطور صریح
GoogleMap.stopAnimation()را فراخوانی کند،OnCameraMoveCanceled()بازخوان فراخوانی میشود، اما بازخوانonCameraMoveStarted()فراخوانی نمیشود فراخوانی میشود.
برای تنظیم شنونده روی نقشه، روش تنظیم شنونده مربوطه را فراخوانی کنید.
برای مثال، برای درخواست تماس از OnCameraMoveStartedListener، با
GoogleMap.setOnCameraMoveStartedListener() تماس بگیرید.
میتوانید هدف دوربین (عرض جغرافیایی/طول جغرافیایی)، بزرگنمایی، زاویه افقی، و زاویه عمودی را از CameraPosition دریافت کنید. برای جزئیات مربوط به این داراییها، به راهنمای
موقعیت دوربین مراجعه کنید.
رویدادهای کسبوکارها و دیگر نقاط جالب
بهطور پیشفرض، نقاط موردعلاقه (POIs) همراه با نمادهای مربوطه در نقشه پایه نشان داده میشوند. نقاط موردعلاقه شامل پارکها، مدارس، ساختمانهای دولتی، و غیره، و همچنین نقاط موردعلاقه کسبوکار مانند فروشگاهها، رستورانها، و هتلها میشود.
میتوانید به رویدادهای کلیک روی نقطه موردعلاقه پاسخ دهید. راهنمای کسبوکارها و دیگر نقاط موردعلاقه را ببینید.
رویدادهای نقشه داخلی
میتوانید از رویدادها برای پیدا کردن و سفارشیسازی سطح فعال نقشه داخلی استفاده کنید. از میانای OnIndoorStateChangeListener برای تنظیم شنوندهای استفاده کنید که وقتی ساختمان جدیدی متمرکز میشود یا سطح جدیدی در ساختمان فعال میشود، فراخوانده شود.
با فراخواندن
GoogleMap.getFocusedBuilding()، ساختمانی را که درحالحاضر در کانون توجه است دریافت کنید.
قرار دادن مرکز نقشه روی طول/عرض جغرافیایی خاصی معمولاً ساختمان را در آن طول/عرض جغرافیایی به شما نشان میدهد، اما این کار تضمینی نیست.
سپس میتوانید با فراخوانی IndoorBuilding.getActiveLevelIndex()، سطح فعال کنونی را پیدا کنید.
Kotlin
map.focusedBuilding?.let { building: IndoorBuilding -> val activeLevelIndex = building.activeLevelIndex val activeLevel = building.levels[activeLevelIndex] }
جاوا
IndoorBuilding building = map.getFocusedBuilding(); if (building != null) { int activeLevelIndex = building.getActiveLevelIndex(); IndoorLevel activeLevel = building.getLevels().get(activeLevelIndex); }
این ویژگی زمانی مفید است که بخواهید نشانگذاری سفارشی برای سطح فعال نشان دهید، مانند نشانگرها، رونهادهای زمین، رونهادهای کاشی، چندضلعیها، چندخطیها، و دیگر شکلها.
نکته: برای برگشتن به سطح خیابان، سطح پیشفرض را ازطریق
IndoorBuilding.getDefaultLevelIndex() دریافت کنید و آن را ازطریق
IndoorLevel.activate() بهعنوان سطح فعال تنظیم کنید.
رویدادهای نشانگر و پنجره اطلاعات
میتوانید با تنظیم شنونده مربوطه روی شیء GoogleMap که نشانگر به آن تعلق دارد، به رویدادهای نشانگر، ازجمله رویدادهای کلیک و کشیدن نشانگر، گوش دهید و پاسخ دهید. راهنمای رویدادهای نشانگر را ببینید.
همچنین میتوانید به رویدادها در پنجرههای اطلاعات گوش دهید.
رویدادهای شکل و رونهاد
میتوانید به رویدادهای کلیک روی چندخطیها، چندضلعیها، دایرهها، و برافزاهای زمین گوش دهید و به آنها پاسخ دهید.
رویدادهای مکان
برنامه شما میتواند به رویدادهای زیر که مربوط به لایه «مکان من» است پاسخ دهد:
- اگر کاربر روی دکمه «مکان من» کلیک کند، برنامه شما یک
onMyLocationButtonClick()برگشت تماس ازGoogleMap.OnMyLocationButtonClickListenerدریافت میکند. - اگر کاربر روی نقطه آبی «مکان من» کلیک کند، برنامهتان یک
onMyLocationClick()فراخوانی برگشتی ازGoogleMap.OnMyLocationClickListenerدریافت میکند.
برای جزئیات، راهنمای لایه «مکان من» را ببینید.