事件

選取平台: Android iOS JavaScript

您可以使用 Maps SDK for Android 監聽地圖上的事件。

程式碼範例

GitHub 上的 ApiDemos 存放區有事件和監聽器的說明範例:

Kotlin

Java

地圖點擊/長按事件

您可以使用 OnMapClickListener 回應輕觸地圖上某個地點的使用者,呼叫 GoogleMap.setOnMapClickListener(OnMapClickListener) 則可在地圖上進行設定。使用者按一下 (輕觸) 地圖上某個位置時,您會收到 onMapClick(LatLng) 事件,指出使用者在地圖上點按的位置。請注意,如果您需要在螢幕上顯示對應的位置 (以像素為單位),可以從地圖取得 Projection,這樣就能在經緯度座標和螢幕像素座標之間進行轉換。

您也可以透過 OnMapLongClickListener 監聽長按事件,呼叫 GoogleMap.setOnMapLongClickListener(OnMapLongClickListener) 則可在地圖上進行設定。這個事件監聽器的運作方式與點擊事件監聽器類似,出現長按事件時,就會收到 onMapLongClick(LatLng) 回呼通知。

停用精簡模式中的點擊事件

如要停用精簡模式地圖的點擊事件,請在包含 MapViewMapFragment 的檢視畫面呼叫 setClickable()。舉例來說,在清單檢視中顯示一或多張地圖時,您希望點擊事件叫用與地圖無關的動作,這項功能就能派上用場。

停用點擊事件的選項僅適用於精簡模式。停用點擊事件也會使標記無法點按,但不影響地圖上的其他控制項。

對於 MapView

KotlinJava


val mapView
= findViewById<MapView>(R.id.mapView)
mapView
.isClickable = false

     

MapView mapView = findViewById(R.id.mapView);
mapView
.setClickable(false);

     

對於 MapFragment

KotlinJava


val mapFragment
= supportFragmentManager
   
.findFragmentById(R.id.map) as SupportMapFragment
val view
= mapFragment.view
view
?.isClickable = false

     

SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
   
.findFragmentById(R.id.map);
View view = mapFragment.getView();
view
.setClickable(false);

     

攝影機變更事件

地圖檢視是模擬向下俯瞰平面的攝影機。您可以變更攝影機的屬性,調整地圖的縮放等級、可視區域和視角。請參閱攝影機指南。使用者也可用手勢調整攝影機。

使用攝影機變更事件監聽器,您就可以追蹤攝影機的動作。您的應用程式可接收攝影機動作開始、進行中和結束事件的通知。您也可以查看促使攝影機移動的「原因」,例如使用者手勢、內建 API 動畫或由開發人員控制的動作。

以下範例說明所有可用的攝影機事件監聽器:

KotlinJava

/*
 * 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 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.PolylineOptions

/**
 * This shows how to change the camera position for the map.
 */

class CameraDemoActivity :
       
AppCompatActivity(),
       
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

   
override fun onCreate(savedInstanceState: Bundle?) {
       
super.onCreate(savedInstanceState)
        setContentView
(R.layout.camera_demo)
        animateToggle
= findViewById(R.id.animate)
        customDurationToggle
= findViewById(R.id.duration_toggle)
        customDurationBar
= findViewById(R.id.duration_bar)

        updateEnabledState
()

        val mapFragment
= supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
        mapFragment
.getMapAsync(this)
   
}

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

   
/**
     * 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 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.PolylineOptions;

/**
 * This shows how to change the camera position for the map.
 */

public class CameraDemoActivity extends AppCompatActivity 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;

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
        setContentView
(R.layout.camera_demo);
        animateToggle
= findViewById(R.id.animate);
        customDurationToggle
= findViewById(R.id.duration_toggle);
        customDurationBar
= findViewById(R.id.duration_bar);

        updateEnabledState
();

       
SupportMapFragment mapFragment =
               
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment
.getMapAsync(this);
   
}

   
@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
        map
.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-33.87365, 151.20689), 10));
   
}

   
/**
     * 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, 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);
   
}
}

您可以使用下列攝影機事件監聽器:

  • 攝影機開始移動時,系統會叫用 OnCameraMoveStartedListeneronCameraMoveStarted() 回呼,回呼方法則會接收攝影機動作的 reason。原因可能是下列其中一項:

    • REASON_GESTURE 表示攝影機因回應使用者在地圖上的手勢而移動,這類手勢包括平移、傾斜、雙指撥動縮放或旋轉地圖等。
    • REASON_API_ANIMATION 表示 API 為回應使用者的非手勢動作 (例如輕觸縮放按鈕、輕觸「我的位置」按鈕或點選標記) 而移動攝影機。
    • REASON_DEVELOPER_ANIMATION 表示應用程式啟動了攝影機動作。
  • 使用者與觸控螢幕進行互動或攝影機移動時,系統會多次叫用 OnCameraMoveListeneronCameraMove() 回呼。API 會在每個頁框叫用回呼一次,瞭解這一點能幫助您掌握系統叫用回呼的頻率。不過請注意,這個回呼是以非同步方式叫用,因此會與螢幕上顯示的內容不同步。此外也請注意,在一個 onCameraMove() 回呼和下一個回呼之間,攝影機位置可能會維持不變。

  • 當攝影機停止移動且使用者停止與地圖互動時,系統會叫用 OnCameraIdleListenerOnCameraIdle() 回呼。

  • 目前的攝影機動作中斷時,系統會叫用 OnCameraMoveCanceledListenerOnCameraMoveCanceled() 回呼。在 OnCameraMoveCanceled() 回呼之後,系統會立即使用新的 reason 叫用 onCameraMoveStarted() 回呼。

    如果您的應用程式明確呼叫 GoogleMap.stopAnimation(),系統會叫用 OnCameraMoveCanceled() 回呼,但不會叫用 onCameraMoveStarted() 回呼。

如要在地圖上設定事件監聽器,請呼叫相關設定方法。 舉例來說,如要向 OnCameraMoveStartedListener 要求回呼,請呼叫 GoogleMap.setOnCameraMoveStartedListener()

您可以從 CameraPosition 取得攝影機的目標 (緯度/經度)、縮放、方位和傾斜角度。如要進一步瞭解這些屬性,請參閱攝影機位置指南。

商家和其他搜尋點的事件

根據預設,搜尋點與對應的圖示會一併顯示在基本地圖上。搜尋點包括公園、學校、政府大樓等,也包括像商店、餐廳和飯店等商家搜尋點。

您可以回應搜尋點上的點擊事件。請參閱商家和其他搜尋點指南。

室內地圖事件

您可以使用事件來尋找及自訂室內地圖的顯示樓層。如使用 OnIndoorStateChangeListener 介面設定事件監聽器,就能在焦點移至新的建築物或建築物展現新樓層時呼叫監聽器。

呼叫 GoogleMap.getFocusedBuilding() 可存取目前要檢視的建築物。 將地圖中心置於特定經緯度時,通常會顯示該經緯度的建築物 (但不保證會如此)。

接著,您可以呼叫 IndoorBuilding.getActiveLevelIndex() 來尋找目前的顯示樓層。

KotlinJava


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 物件設定對應的事件監聽器,藉此監聽並回應標記事件 (包括標記點擊和拖曳事件)。請參閱標記事件指南。

您也可以監聽資訊視窗中的事件。

形狀和疊加層事件

您可以監聽並回應折線多邊形圓形區域疊加層上的點擊事件。

位置事件

應用程式可以回應下列與「我的位置」圖層相關的事件:

詳情請參閱我的位置圖層指南。