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)); } }
关键改进点说明
- 布局简化:去掉多余的RelativeLayout,直接让ImageView居中,减少层级,避免位置计算的小误差
- Projection实时获取:每次转换坐标时都从
mMap.getProjection()拿最新的投影对象,因为地图移动后,屏幕坐标和经纬度的对应关系会变化 - 监听时机优化:用
OnCameraIdleListener代替OnCameraMoveListener,在地图停止滚动时才计算经纬度,避免频繁触发,提升性能 - 移除布局监听器:布局完成后及时移除
OnGlobalLayoutListener,防止内存泄漏 - 初始位置正确获取:等Marker布局完成后再计算初始经纬度,解决了你初始值为0.0的问题
这样修改后,就能完美实现你想要的功能:静态Marker固定在屏幕中心,地图滚动停止后,自动获取Marker下方地点的经纬度。
内容的提问来源于stack exchange,提问作者jobin
相关产品推荐
相关产品推荐

