Как плавно переместить текущую позицию в Google Maps? - PullRequest
0 голосов
/ 19 мая 2018

В моем проекте Android мне нужно, чтобы при движении автомобиля положение маркера также плавно перемещалось, но при изменении местоположения маркер переходит из одного положения в другое, оно не перемещается плавно.

Я много искал, но не получил результата.
Я не знаю, как лучше.Пожалуйста, дайте мне полное руководство.

большое спасибо

Обновление

@ AnkitMehta спасибо за ответ

весь код вMapsActivity:

import android.Manifest;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.location.Location;
import android.os.Build;
import android.os.Handler;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MapStyleOptions;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

  private GoogleMap mMap;
  SupportMapFragment mapFragment;
  LocationRequest mLocationRequest;
  GoogleApiClient mGoogleApiClient;
  Location mLastLocation;
  Marker mCurrLocationMarker;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
  }

  @Override
  protected void onPause() {
    super.onPause();

    //stop Location updates when Activity is no longer active
    if (mGoogleApiClient != null) {
      LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
    }
  }


  @Override
  public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;

    try {
      // Customise the styling of the base map using a JSON object defined
      // in a raw resource file.
      boolean success = googleMap.setMapStyle(
        MapStyleOptions.loadRawResourceStyle(
          this, R.raw.style_json));

      if (!success) {
        Log.e("LOG" , "Style parsing failed.");
      }
    } catch (Resources.NotFoundException e) {
      Log.e("LOG", "Can't find style. Error: ", e);
    }

    //initialize Google play Services
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        // Location Permission already granted
        buildGoogleApiClient();
        mMap.setMyLocationEnabled(true);

      } else {
        // Request Location Permission
        checkLocationPermission();
      }
    } else {
      buildGoogleApiClient();
      mMap.setMyLocationEnabled(true);
    }


  }

  protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
      .addConnectionCallbacks(this)
      .addOnConnectionFailedListener(this)
      .addApi(LocationServices.API)
      .build();
    mGoogleApiClient.connect();
  }


  @Override
  public void onConnected(@Nullable Bundle bundle) {
    mLocationRequest = new LocationRequest();
    //mLocationRequest.setInterval(30000);
    //mLocationRequest.setFastestInterval(30000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
      LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }
  }

  @Override
  public void onConnectionSuspended(int i) {

  }

  @Override
  public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

  }

  @Override
  public void onLocationChanged(Location location) {
    mLastLocation = location;
    if (mCurrLocationMarker != null) {
      mCurrLocationMarker.remove();
    }

    //Place current location marker
    LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
    animateMarker(latLng, latLng, true);


    //move map camera
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng,11));
    mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 11));
  }

  public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
  private void checkLocationPermission() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
      != PackageManager.PERMISSION_GRANTED) {

      // Should we show an explanation?
      if (ActivityCompat.shouldShowRequestPermissionRationale(this,
        Manifest.permission.ACCESS_FINE_LOCATION)) {

        // Show an explanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.
        new AlertDialog.Builder(this)
          .setTitle("Location Permission Needed")
          .setMessage("This app needs the Location permission, please accept to use location functionality")
          .setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
              //Prompt the user once explanation has been shown
              ActivityCompat.requestPermissions(MapsActivity.this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                MY_PERMISSIONS_REQUEST_LOCATION );
            }
          })
          .create()
          .show();


      } else {
        // No explanation needed, we can request the permission.
        ActivityCompat.requestPermissions(this,
          new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
          MY_PERMISSIONS_REQUEST_LOCATION );
      }
    }
  }

  @Override
  public void onRequestPermissionsResult(int requestCode,
                                         String permissions[], int[] grantResults) {
    switch (requestCode) {
      case MY_PERMISSIONS_REQUEST_LOCATION: {
        // If request is cancelled, the result arrays are empty.
        if (grantResults.length > 0
          && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

          // permission was granted, yay! Do the
          // location-related task you need to do.
          if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED) {

            if (mGoogleApiClient == null) {
              buildGoogleApiClient();
            }
            mMap.setMyLocationEnabled(true);
          }

        } else {

          // permission denied, boo! Disable the
          // functionality that depends on this permission.
          Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
        }
        return;
      }

      // other 'case' lines to check for other
      // permissions this app might request
    }
  }


  //This methos is used to move the marker of each car smoothly when there are any updates of their position
  public void animateMarker(final LatLng startPosition, final LatLng toPosition,
                            final boolean hideMarker) {


    final Marker marker = mMap.addMarker(new MarkerOptions()
      .position(startPosition)
      .icon(BitmapDescriptorFactory.fromResource(R.drawable.car)));


    final Handler handler = new Handler();
    final long start = SystemClock.uptimeMillis();

    final long duration = 1000;
    final Interpolator interpolator = new LinearInterpolator();

    handler.post(new Runnable() {
      @Override
      public void run() {
        long elapsed = SystemClock.uptimeMillis() - start;
        float t = interpolator.getInterpolation((float) elapsed
          / duration);
        double lng = t * toPosition.longitude + (1 - t)
          * startPosition.longitude;
        double lat = t * toPosition.latitude + (1 - t)
          * startPosition.latitude;

        marker.setPosition(new LatLng(lat, lng));

        if (t < 1.0) {
          // Post again 16ms later.
          handler.postDelayed(this, 16);
        } else {
          if (hideMarker) {
            marker.setVisible(false);
          } else {
            marker.setVisible(true);
          }
        }
      }
    });
  }
}

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Переопределите этот метод:

@Override
public void onLocationChange(Location location) {
     LatLng latLng = new LatLng(location.latitude, location.longitude);
     refreshMapPosition(latLng, 45)
}


private void refreshMapPosition(LatLng pos, float angle) {
    CameraPosition.Builder positionBuilder = new CameraPosition.Builder();
    positionBuilder.target(pos);
    positionBuilder.zoom(15f);
    positionBuilder.bearing(angle);
    positionBuilder.tilt(60);
    map.animateCamera(CameraUpdateFactory.newCameraPosition(positionBuilder.build()));
}

Этот переопределенный метод был реализован в классах GoogleMap, и переменная карты является переменной, которую мы определяем для загрузки экземпляра карты Google.

Пожалуйста, обратитесь: https://developers.google.com/maps/documentation/android-sdk/views

0 голосов
/ 19 мая 2018
CameraPosition cameraPosition = new CameraPosition.Builder()
                                .target(latLng)
                                .build();
CameraUpdate cu = CameraUpdateFactory.newCameraPosition(cameraPosition);
map.animateCamera(cu);

это переместится к широте, выбранной с помощью анимации (используется положение камеры и обновление камеры)

...