2

我是 android 开发的新手,正在开发一个需要谷歌地图活动的应用程序。我面临的问题是,当我尝试平移(或滚动)地图时,我会立即重生到我最初设置的当前位置。一点帮助会很棒,因为我被困在这一点上并且无法找到解决方案。这是代码: -

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    binding = ActivityMapsBinding.inflate(getLayoutInflater());
    setContentView(binding.getRoot());

    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}



@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    mMap.getUiSettings().setScrollGesturesEnabled(true);
    locationManager=(LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
    locationListener=new LocationListener() {
        @Override
        public void onLocationChanged(@NonNull Location location) {
            centerOnMap(location,"Your Location");
        }
    };

    if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED)
    {
        ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
    }
    else{
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
        Location lastKnownLocation=locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        centerOnMap(lastKnownLocation,"Your Location");
    }
}

public void centerOnMap(Location location,String address)
{
    LatLng userLocation = new LatLng(location.getLatitude(),location.getLongitude());
    mMap.addMarker(new MarkerOptions().position(userLocation).title(address));
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull @org.jetbrains.annotations.NotNull String[] permissions, @NonNull @org.jetbrains.annotations.NotNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED)
    {
        if(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED){
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
        }

    }
}

}

4

2 回答 2

1

您可能有但未说明的一项要求是:

lastLocation可用并且用户没有移动地图时,则将地图置于该位置的中心。如果用户已经移动了地图,则不要将地图居中。 在任何一种情况下,在用户的位置添加一个标记。

在走得太远之前,必须注意谷歌地图提供的功能类似于您想要实现的功能,尽管您仍然需要“移动相机”。标记是一个蓝色球,而不是典型的标记。见myMap.setMyLocationEnabled(true)。就是这样!当您获得地图权限时执行此操作。

但是如果您不想使用它,那么这里是您需要的简单更改。

请记住,LocationManager getLastKnownLocation如果设备(还)没有,则可以返回 null。所以我建议做一个无关紧要的小改动——让位置监听器完成所有工作并摆脱这个特殊情况:

// this is where you initially check permissions and have them.
else{
    locationManager.requestLocationUpdates (LocationManager.GPS_PROVIDER,0,0,locationListener);
    // Here I removed the last location centering and let the
    // location listener always handle it.
}

因此,这开启了用户与地图交互并最终到达最后一个位置的可能性。我理解这是您要解决的问题。

(顺便说一句,在我看来,您将android.location.LocationManagerFusedLocationProviderApi(com.google.android.gms.location) 混合使用,因此由于 s 不兼容,我无法编译您的代码LocationListener。不幸的是,谷歌地图有两个LocationListener类,以便确定您必须包含您的导入以进一步了解。)

无论如何...

当地图第一次准备好 ( onMapReady) 时,地图的相机以 为中心(0,0)。您可以随时使用LatLng tgtCtr = mMap.getCameraPosition().target;.

奇怪的是,要知道用户是否以任何方式与地图交互并不简单:滚动事件会产生相机变化,而触摸事件会产生单独的事件。不能单独使用相机更改,因为您的代码或用户可能只是缩放而不移动地图。你可以走这条路,但为了这个答案的目的,为了简单起见,使用了相机目标。

声明一个类实例变量(您定义的同一区域mMap):

LatLng tgtCtr;

所以在你onMapReady分配后mMap做:

tgtCtr = mMap.getCameraPosition().target;

因此,假设您发布的代码存在(非常接近),那么这些更改可能会有所帮助:

// This change simply restricts centering of the map on location
// update to only when user has not moved the map (scrolled).

@Override
public void onLocationChanged(@NonNull Location location) {
    LatLng currentCtr = mMap.getCamaraPosition().target;
    
    // This is not the ideal check since `double` comparisons 
    // should account for epsilon but in this case of (0,0) it should work.
    
    // Alternatively you could compute the distance of current
    // center to (0,0) and then use an epsilon: 
    //    see `com.google.maps.android.SphericalUtil.computeDistanceBetween`.
    
    if (currentCtr.latitude == 0 && currentCtr.longitude == 0) {
        centerOnMap(location,"Your Location");
    }
}

保存为用户位置添加的标记似乎也是一个好主意 - 这是可选的,但可能会派上用场,以防止在该位置添加多个标记:

// Define a class instance variable
Marker myLocMarker = nulll;

// and then in centerOnMap
public void centerOnMap(Location location, String address)
{
    // ... other code

    if (myLocMarker == null) {
        myLocMarker = mMap.addMarker(new MarkerOptions().position(userLocation).title(address));
    }

    // ... more code
}

所以真正唯一的困难是弄清楚“用户是否移动了地图”。在这种情况下,根据最初的要求,您不想移动地图。

于 2021-05-30T15:18:32.697 回答
1

正如您在评论部分提到的那样,使用 FusedLocationProviderClient 而不是 LocationManager。添加 implementation 'com.google.android.gms:play-services-location:17.0.0'应用程序级别的gradle。并且不要忘记为精细位置添加清单权限。

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

private GoogleMap mMap;

FusedLocationProviderClient mFusedLocationClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

}

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

    getLastLocation();
    mMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
        @Override
        public void onMapLongClick(@NonNull LatLng latLng) {

            Location location = new Location(LocationManager.GPS_PROVIDER);
            location.setLatitude(latLng.latitude);
            location.setLongitude(latLng.longitude);
            centerOnMap(location,"Your location");
        }
    });
}


@SuppressLint("MissingPermission")
private void getLastLocation() {
    if (checkPermissions()) {
        if (isLocationEnabled()) {
            mFusedLocationClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
                @Override
                public void onComplete(@NonNull Task<Location> task) {
                    Location location = task.getResult();
                    if (location == null) {
                        requestNewLocationData();
                    } else {
                        centerOnMap(location,"Your Location");
                    }
                }
            });
        } else {
            Toast.makeText(this, "Please turn on" + " your location...", Toast.LENGTH_LONG).show();
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivity(intent);
        }
    } else {
        requestPermissions();
    }
}

@SuppressLint("MissingPermission")
private void requestNewLocationData() {
    LocationRequest mLocationRequest = new LocationRequest();
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setInterval(5);
    mLocationRequest.setFastestInterval(0);
    mLocationRequest.setNumUpdates(1);
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}

private LocationCallback mLocationCallback = new LocationCallback() {

    @Override
    public void onLocationResult(LocationResult locationResult) {
        Location mLastLocation = locationResult.getLastLocation();
        centerOnMap(mLastLocation,"Your Location");
    }
};

private boolean checkPermissions() {
    return ActivityCompat.checkSelfPermission(this,   Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}

private void requestPermissions() {
    ActivityCompat.requestPermissions(this, new String[]{
            Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}

private boolean isLocationEnabled() {
    LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}

public void centerOnMap(Location location,String address)
{
    LatLng userLocation = new LatLng(location.getLatitude(),location.getLongitude());
    mMap.clear();
    mMap.addMarker(new MarkerOptions().position(userLocation).title(address));
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED)
    {
        getLastLocation();
    }
}

}

于 2021-05-31T11:10:37.587 回答