You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android地图滚动时获取静态Marker下方位置经纬度的实现问询

嘿,我看你正在做类似Uber/Ola的地图选点功能——静态Marker固定在屏幕中心,地图滚动时获取它下方的经纬度对吧?你的代码已经有了基础,但有几个地方需要调整,来解决初始经纬度为0.0的问题,同时优化实时获取的逻辑。

首先简化布局文件(map.xml)

你原来的布局里嵌套了不必要的RelativeLayout,直接让ImageView居中就能达到效果,这样减少布局层级,还能避免位置计算的偏差:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 地图Fragment -->
    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        map:layout_constraintBottom_toBottomOf="parent"
        map:layout_constraintEnd_toEndOf="parent"
        map:layout_constraintStart_toStartOf="parent"
        map:layout_constraintTop_toTopOf="parent"
        tools:context=".MapsActivity" />

    <!-- 静态Marker:直接居中显示 -->
    <ImageView
        android:id="@+id/marker"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@drawable/gps"
        map:layout_constraintBottom_toBottomOf="parent"
        map:layout_constraintEnd_toEndOf="parent"
        map:layout_constraintStart_toStartOf="parent"
        map:layout_constraintTop_toTopOf="parent" />

    <!-- 搜索输入框 -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="@drawable/edttxt_bg"
        map:layout_constraintTop_toTopOf="parent"
        map:layout_constraintStart_toStartOf="parent"
        map:layout_constraintEnd_toEndOf="parent"
        map:layout_constraintVertical_bias="0.035" />

</android.support.constraint.ConstraintLayout>

然后修正Java代码(MapActivity.java)

你的现有代码有几个关键问题:比如初始时projection获取过早,地图移动时没有用最新的投影对象,还有布局监听器没移除可能导致内存泄漏。我帮你调整了这些点,同时优化了监听逻辑:

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    private ImageView marker;
    private int[] outLocation = new int[2];

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

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

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        mMap.getUiSettings().setMyLocationButtonEnabled(true);

        // 等Marker布局完成后,获取初始中心位置的经纬度
        marker.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                // 布局完成后立刻移除监听器,避免重复触发
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    marker.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                } else {
                    marker.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                }
                // 获取初始位置的经纬度
                getMarkerUnderLatLng();
            }
        });

        // 监听地图相机停止移动,实时获取Marker下方的经纬度
        mMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
            @Override
            public void onCameraIdle() {
                // 相机停止滚动时再计算,比监听CameraMove更高效,避免频繁计算
                getMarkerUnderLatLng();
            }
        });
    }

    // 核心方法:把Marker的屏幕坐标转换成地图经纬度
    private void getMarkerUnderLatLng() {
        // 获取Marker在屏幕上的坐标
        marker.getLocationOnScreen(outLocation);
        // 每次都获取最新的Projection,因为地图移动后投影关系会变
        Projection projection = mMap.getProjection();
        // 转换为经纬度
        LatLng currentLocation = projection.fromScreenLocation(new Point(outLocation[0], outLocation[1]));

        // 这里可以把经纬度用在你需要的地方,比如打印或者更新UI
        Log.e("当前纬度", String.valueOf(currentLocation.latitude));
        Log.e("当前经度", String.valueOf(currentLocation.longitude));
    }
}

关键改进点说明

  1. 布局简化:去掉多余的RelativeLayout,直接让ImageView居中,减少层级,避免位置计算的小误差
  2. Projection实时获取:每次转换坐标时都从mMap.getProjection()拿最新的投影对象,因为地图移动后,屏幕坐标和经纬度的对应关系会变化
  3. 监听时机优化:用OnCameraIdleListener代替OnCameraMoveListener,在地图停止滚动时才计算经纬度,避免频繁触发,提升性能
  4. 移除布局监听器:布局完成后及时移除OnGlobalLayoutListener,防止内存泄漏
  5. 初始位置正确获取:等Marker布局完成后再计算初始经纬度,解决了你初始值为0.0的问题

这样修改后,就能完美实现你想要的功能:静态Marker固定在屏幕中心,地图滚动停止后,自动获取Marker下方地点的经纬度。

内容的提问来源于stack exchange,提问作者jobin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:35:16