กิจกรรม

เลือกแพลตฟอร์ม Android iOS JavaScript

เมื่อใช้ Maps SDK สําหรับ Android คุณจะฟังเหตุการณ์บนแผนที่ได้

ตัวอย่างโค้ด

ที่เก็บ ApiDemos ใน GitHub มีตัวอย่างที่แสดงเหตุการณ์และผู้ฟัง ดังนี้

Kotlin

  • EventsDemoActivity: แมปเหตุการณ์การคลิกและการเปลี่ยนแปลงกล้อง
  • CameraDemoActivity: เหตุการณ์การเปลี่ยนแปลงของกล้อง
  • CircleDemoActivity: เหตุการณ์การคลิกและลากเครื่องหมาย
  • GroundOverlayDemoActivity: เหตุการณ์การคลิกการวางซ้อนพื้น
  • IndoorDemoActivity: เหตุการณ์แผนที่ในอาคาร
  • MarkerDemoActivity: เหตุการณ์เครื่องหมายและหน้าต่างข้อมูล
  • PolygonDemoActivity: เหตุการณ์ Polygon

Java

  • EventsDemoActivity: แมปเหตุการณ์การคลิกและการเปลี่ยนแปลงกล้อง
  • CameraDemoActivity: เหตุการณ์การเปลี่ยนแปลงของกล้อง
  • CircleDemoActivity: เหตุการณ์การคลิกและลากเครื่องหมาย
  • GroundOverlayDemoActivity: เหตุการณ์การคลิกการวางซ้อนพื้น
  • IndoorDemoActivity: เหตุการณ์แผนที่ในอาคาร
  • MarkerDemoActivity: เหตุการณ์เครื่องหมายและหน้าต่างข้อมูล
  • PolygonDemoActivity: เหตุการณ์ Polygon

แมปเหตุการณ์การคลิก / การคลิกค้าง

หากต้องการตอบสนองต่อผู้ใช้ที่แตะจุดบนแผนที่ ให้ใช้ OnMapClickListener ซึ่งคุณตั้งค่าบนแผนที่ได้โดยเรียกใช้ GoogleMap.setOnMapClickListener(OnMapClickListener) เมื่อผู้ใช้คลิก (แตะ) ที่ใดก็ตามบนแผนที่ คุณจะได้รับonMapClick(LatLng)เหตุการณ์ที่ระบุตําแหน่งในแผนที่ที่ผู้ใช้คลิก โปรดทราบว่าหากต้องการตำแหน่งที่สอดคล้องกับตำแหน่งบนหน้าจอ (เป็นพิกเซล) คุณสามารถรับ Projection จากแผนที่ ซึ่งจะช่วยให้คุณแปลงระหว่างพิกัดละติจูด/ลองจิจูดกับพิกัดพิกเซลของหน้าจอได้

นอกจากนี้ คุณยังคอยฟังเหตุการณ์การคลิกค้างไว้ได้ด้วย OnMapLongClickListener ซึ่งตั้งค่าได้ในแผนที่โดยเรียกใช้ GoogleMap.setOnMapLongClickListener(OnMapLongClickListener) Listener นี้ทํางานคล้ายกับ Listener การคลิกและจะได้รับการแจ้งเตือนเมื่อเกิดเหตุการณ์การคลิกค้างไว้ด้วย onMapLongClick(LatLng) callback

การปิดใช้เหตุการณ์การคลิกในโหมด Lite

หากต้องการปิดใช้เหตุการณ์การคลิกบนแผนที่ในโหมด Lite ให้เรียกใช้ setClickable() ในมุมมองที่มี MapView หรือ MapFragment ซึ่งมีประโยชน์ เช่น เมื่อแสดงแผนที่หรือแผนที่ในมุมมองรายการที่คุณต้องการให้เหตุการณ์การคลิกเรียกการดำเนินการที่ไม่เกี่ยวข้องกับแผนที่

ตัวเลือกในการปิดใช้เหตุการณ์คลิกจะใช้ได้เฉพาะในโหมด Lite เท่านั้น การปิดใช้เหตุการณ์การคลิกจะทำให้เครื่องหมายคลิกไม่ได้ด้วย การดำเนินการนี้จะไม่ส่งผลต่อการควบคุมอื่นๆ ในแผนที่

สำหรับ MapView

Kotlin

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

      

Java

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

      

สำหรับ MapFragment

Kotlin

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

      

Java

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

      

เหตุการณ์การเปลี่ยนแปลงของกล้อง

มุมมองแผนที่จะจำลองเป็นกล้องที่มองลงมาบนพื้นผิวเรียบ คุณสามารถเปลี่ยนคุณสมบัติของกล้องเพื่อส่งผลต่อระดับการซูม พอร์ตดู และมุมมองของแผนที่ได้ ดูคู่มือเกี่ยวกับกล้อง นอกจากนี้ ผู้ใช้ยังควบคุมกล้องได้ด้วยท่าทางสัมผัส

คุณติดตามการเคลื่อนไหวของกล้องได้โดยใช้ Listeners สำหรับการเปลี่ยนแปลงของกล้อง แอปของคุณจะได้รับการแจ้งเตือนสำหรับเหตุการณ์เริ่มต้น ต่อเนื่อง และสิ้นสุดการเคลื่อนไหวของกล้อง นอกจากนี้ คุณยังดูสาเหตุที่กล้องเคลื่อนไหวได้ด้วย ไม่ว่าจะเป็นการเคลื่อนไหวที่เกิดจากท่าทางสัมผัสของผู้ใช้ ภาพเคลื่อนไหว 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 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)
    }
}

Java

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

เครื่องมือฟังเสียงจากกล้องที่ใช้ได้มีดังนี้

  • ระบบจะเรียกใช้ onCameraMoveStarted() callback ของ OnCameraMoveStartedListener เมื่อกล้องเริ่มเคลื่อนไหว เมธอด Callback จะได้รับ reason สำหรับการเคลื่อนไหวของกล้อง สาเหตุอาจเป็นอย่างใดอย่างหนึ่งต่อไปนี้

    • REASON_GESTURE บ่งบอกว่ากล้องเคลื่อนไหวตามท่าทางสัมผัสของผู้ใช้บนแผนที่ เช่น การแพน การเอียง การบีบนิ้วเพื่อซูม หรือการหมุนแผนที่
    • REASON_API_ANIMATION บ่งบอกว่า API ได้ย้ายกล้องเพื่อตอบสนองต่อการกระทำของผู้ใช้ที่ไม่ใช่ท่าทางสัมผัส เช่น การแตะปุ่มซูม การแตะปุ่ม "ตำแหน่งของฉัน" หรือการคลิกเครื่องหมาย
    • REASON_DEVELOPER_ANIMATION บ่งบอกว่าแอปของคุณได้เริ่มการเคลื่อนไหวของกล้องแล้ว
  • ระบบเรียกใช้ onCameraMove() callback ของ OnCameraMoveListener หลายครั้งขณะที่กล้องเคลื่อนไหวหรือผู้ใช้โต้ตอบกับหน้าจอสัมผัส ข้อมูลว่า API จะเรียกใช้การเรียกกลับ 1 ครั้งต่อเฟรมจะเป็นประโยชน์ในการใช้เป็นแนวทางเกี่ยวกับความถี่ในการเรียกใช้การเรียกกลับ อย่างไรก็ตาม โปรดทราบว่าระบบจะเรียกใช้การเรียกกลับนี้แบบไม่พร้อมกัน ดังนั้นจึงไม่ได้ซิงค์กับสิ่งที่ปรากฏบนหน้าจอ นอกจากนี้ โปรดทราบว่าตำแหน่งของกล้องอาจไม่มีการเปลี่ยนแปลงระหว่างonCameraMove()การเรียกกลับครั้งหนึ่งกับครั้งถัดไป

  • ระบบจะเรียกใช้ OnCameraIdle() callback ของ OnCameraIdleListener เมื่อกล้องหยุดเคลื่อนไหวและผู้ใช้หยุดโต้ตอบกับแผนที่

  • ระบบจะเรียกใช้ OnCameraMoveCanceled() callback ของ OnCameraMoveCanceledListener เมื่อการเคลื่อนไหวของกล้องปัจจุบันถูกขัดจังหวะ ทันทีหลังจากการเรียกกลับ OnCameraMoveCanceled() ระบบจะเรียกใช้การเรียกกลับ onCameraMoveStarted() ด้วย reason ใหม่

    หากแอปเรียกใช้ GoogleMap.stopAnimation() อย่างชัดเจน ระบบจะเรียกใช้การเรียกคืน OnCameraMoveCanceled() แต่ไม่เรียกใช้การเรียกคืน onCameraMoveStarted()

หากต้องการตั้งค่า Listener ในแผนที่ ให้เรียกใช้เมธอด set-listener ที่เกี่ยวข้อง ตัวอย่างเช่น หากต้องการขอให้ OnCameraMoveStartedListener โทรกลับ ให้โทรไปที่ GoogleMap.setOnCameraMoveStartedListener()

คุณดูเป้าหมาย (ละติจูด/ลองจิจูด) การซูม ทิศทาง และการเอียงของกล้องได้จาก CameraPosition ดูรายละเอียดเกี่ยวกับพร็อพเพอร์ตี้เหล่านี้ได้ในคำแนะนำเกี่ยวกับตำแหน่งกล้อง

กิจกรรมในธุรกิจและจุดที่น่าสนใจอื่นๆ

โดยค่าเริ่มต้น จุดที่น่าสนใจ (จุดที่น่าสนใจ) จะปรากฏบนแผนที่ฐานพร้อมกับไอคอนที่เกี่ยวข้อง ซึ่งได้แก่ สวนสาธารณะ โรงเรียน อาคารรัฐ และอื่นๆ รวมถึงจุดที่น่าสนใจทางธุรกิจ เช่น ร้านค้า ร้านอาหาร และโรงแรม

คุณตอบสนองต่อเหตุการณ์การคลิกในจุดที่น่าสนใจได้ ดูคู่มือเกี่ยวกับธุรกิจและสถานที่น่าสนใจอื่นๆ

กิจกรรมในแผนที่ในอาคาร

คุณสามารถใช้เหตุการณ์เพื่อค้นหาและปรับแต่งระดับที่ใช้งานอยู่ของแผนที่ในอาคารได้ ใช้อินเทอร์เฟซ OnIndoorStateChangeListener เพื่อตั้งค่าให้เรียกฟังเมื่อโฟกัสอาคารใหม่หรือเปิดใช้งานชั้นใหม่ในอาคาร

ค้นหาอาคารที่โฟกัสอยู่ในปัจจุบันโดยโทรไปที่ GoogleMap.getFocusedBuilding() โดยปกติแล้ว การทำให้แผนที่เป็นศูนย์กลางของละติจูด/ลองจิจูดที่เฉพาะเจาะจงจะแสดงอาคารที่ละติจูด/ลองจิจูดนั้น แต่เราไม่รับประกัน

จากนั้นคุณจะเห็นระดับที่ใช้งานอยู่ในปัจจุบันโดยเรียกใช้ IndoorBuilding.getActiveLevelIndex()

Kotlin

map.focusedBuilding?.let { building: IndoorBuilding ->
    val activeLevelIndex = building.activeLevelIndex
    val activeLevel = building.levels[activeLevelIndex]
}

      

Java

IndoorBuilding building = map.getFocusedBuilding();
if (building != null) {
    int activeLevelIndex = building.getActiveLevelIndex();
    IndoorLevel activeLevel = building.getLevels().get(activeLevelIndex);
}

      

ซึ่งมีประโยชน์ในกรณีที่คุณต้องการแสดงมาร์กอัปที่กําหนดเองสําหรับระดับที่ใช้งานอยู่ เช่น เครื่องหมาย การวางซ้อนพื้นดิน การวางซ้อนไทล์ รูปหลายเหลี่ยม เส้นประกอบ และรูปร่างอื่นๆ

เคล็ดลับ: หากต้องการกลับไปที่ระดับถนน ให้รับระดับเริ่มต้นผ่าน IndoorBuilding.getDefaultLevelIndex() แล้วตั้งเป็นระดับที่ใช้งานอยู่ผ่าน IndoorLevel.activate()

เหตุการณ์เครื่องหมายและหน้าต่างข้อมูล

คุณสามารถรับฟังและตอบสนองต่อเหตุการณ์ของเครื่องหมาย ซึ่งรวมถึงเหตุการณ์การคลิกและการลากเครื่องหมาย โดยการตั้งค่า Listener ที่เกี่ยวข้องบนออบเจ็กต์ GoogleMap ที่เป็นของเคอร์เซอร์ ดูคู่มือเหตุการณ์เครื่องหมาย

นอกจากนี้ คุณยังฟังเหตุการณ์ในหน้าต่างข้อมูลได้ด้วย

รูปร่างและเหตุการณ์วางซ้อน

คุณสามารถฟังและตอบสนองต่อเหตุการณ์การคลิกในเส้นประกอบ รูปหลายเหลี่ยม วงกลม และการวางซ้อนพื้นดิน

เหตุการณ์เกี่ยวกับสถานที่

แอปสามารถตอบสนองต่อเหตุการณ์ต่อไปนี้ที่เกี่ยวข้องกับเลเยอร์ตำแหน่งของฉัน

  • หากผู้ใช้คลิกปุ่ม "ตำแหน่งของฉัน" แอปของคุณจะได้รับonMyLocationButtonClick()การเรียกกลับจาก GoogleMap.OnMyLocationButtonClickListener
  • หากผู้ใช้คลิกจุดสีน้ำเงิน "ตำแหน่งของฉัน" แอปของคุณจะได้รับonMyLocationClick()การเรียกกลับจาก GoogleMap.OnMyLocationClickListener

โปรดดูรายละเอียดที่คู่มือเลเยอร์ตำแหน่งของฉัน