Rotar Marcador y Mover Animación en Mapa como Uber Android

Estoy trabajando en un proyecto similar a UBER, Lyft u OLA es decir. Mapa en el hogar con los coches móviles disponibles. Estoy buscando algún tipo de biblioteca que puede hacer que los coches se muevan y tomar turno suavemente al igual que UBER. Por ahora podía mover el coche suavemente de uno lat-largo a otro con el código abajo. Pero la parte difícil es tomar la vuelta y asegurarse de que el coche cara a frente cuando se mueve a la dirección.

Smooth Moving Código de coche:

final LatLng SomePos = new LatLng(12.7796354, 77.4159606); try { if (googleMap == null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap(); } } googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); googleMap.setMyLocationEnabled(true); googleMap.setTrafficEnabled(false); googleMap.setIndoorEnabled(false); googleMap.setBuildingsEnabled(true); googleMap.getUiSettings().setZoomControlsEnabled(true); googleMap.moveCamera(CameraUpdateFactory.newLatLng(SomePos)); googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder() .target(googleMap.getCameraPosition().target) .zoom(17) .bearing(30) .tilt(45) .build())); myMarker = googleMap.addMarker(new MarkerOptions() .position(SomePos) .icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_launcher)) .title("Hello world")); googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { @Override public boolean onMarkerClick(Marker arg0) { final LatLng startPosition = myMarker.getPosition(); final LatLng finalPosition = new LatLng(12.7801569, 77.4148528); final Handler handler = new Handler(); final long start = SystemClock.uptimeMillis(); final Interpolator interpolator = new AccelerateDecelerateInterpolator(); final float durationInMs = 3000; final boolean hideMarker = false; handler.post(new Runnable() { long elapsed; float t; float v; @Override public void run() { // Calculate progress using interpolator elapsed = SystemClock.uptimeMillis() - start; t = elapsed / durationInMs; LatLng currentPosition = new LatLng( startPosition.latitude * (1 - t) + finalPosition.latitude * t, startPosition.longitude * (1 - t) + finalPosition.longitude * t); myMarker.setPosition(currentPosition); // Repeat till progress is complete. if (t < 1) { // Post again 16ms later. handler.postDelayed(this, 16); } else { if (hideMarker) { myMarker.setVisible(false); } else { myMarker.setVisible(true); } } } }); return true; } }); } catch (Exception e) { e.printStackTrace(); } 

6 Solutions collect form web for “Rotar Marcador y Mover Animación en Mapa como Uber Android”

Recientemente he encontrado el mismo caso de uso. Aquí está mi solución.

En primer lugar, me gustaría dar las gracias a @VipiN por compartir "The Smooth Moving Car Code". Funciona sin problemas.

La segunda parte es colocar el marcador de coche en la dirección correcta y girar de acuerdo con las vueltas. Para lograr esto, calculé el ángulo de rumbo o de rumbo entre dos puntos sucesivos (es decir, las actualizaciones de ubicación que recibe del dispositivo / servidor). Este enlace le ayudará a entender las matemáticas detrás de él.

El siguiente código le dará el rodamiento entre dos ubicaciones:

 private double bearingBetweenLocations(LatLng latLng1,LatLng latLng2) { double PI = 3.14159; double lat1 = latLng1.latitude * PI / 180; double long1 = latLng1.longitude * PI / 180; double lat2 = latLng2.latitude * PI / 180; double long2 = latLng2.longitude * PI / 180; double dLon = (long2 - long1); double y = Math.sin(dLon) * Math.cos(lat2); double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon); double brng = Math.atan2(y, x); brng = Math.toDegrees(brng); brng = (brng + 360) % 360; return brng; } 

Finalmente, necesitamos girar el marcador de coche por el ángulo que obtenemos del método anterior.

 private void rotateMarker(final Marker marker, final float toRotation) { if(!isMarkerRotating) { final Handler handler = new Handler(); final long start = SystemClock.uptimeMillis(); final float startRotation = marker.getRotation(); final long duration = 1000; final Interpolator interpolator = new LinearInterpolator(); handler.post(new Runnable() { @Override public void run() { isMarkerRotating = true; long elapsed = SystemClock.uptimeMillis() - start; float t = interpolator.getInterpolation((float) elapsed / duration); float rot = t * toRotation + (1 - t) * startRotation; marker.setRotation(-rot > 180 ? rot / 2 : rot); if (t < 1.0) { // Post again 16ms later. handler.postDelayed(this, 16); } else { isMarkerRotating = false; } } }); } } 

¡Aclamaciones!

Dado que su bit poco confuso para los usuarios de SO para buscar código de trabajo en dos puestos diferentes. Aquí está el código de trabajo para Rotate y Move Marker que funcionó perfectamente para mí.

En MainActivity.java

 public void rotateMarker(final Marker marker, final float toRotation, final float st) { final Handler handler = new Handler(); final long start = SystemClock.uptimeMillis(); final float startRotation = st; final long duration = 1555; 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); float rot = t * toRotation + (1 - t) * startRotation; marker.setRotation(-rot > 180 ? rot / 2 : rot); if (t < 1.0) { // Post again 16ms later. handler.postDelayed(this, 16); } } }); } public void animateMarker(final LatLng toPosition,final boolean hideMarke) { final Handler handler = new Handler(); final long start = SystemClock.uptimeMillis(); Projection proj = googleMap.getProjection(); Point startPoint = proj.toScreenLocation(m.getPosition()); final LatLng startLatLng = proj.fromScreenLocation(startPoint); final long duration = 5000; 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) * startLatLng.longitude; double lat = t * toPosition.latitude + (1 - t) * startLatLng.latitude; m.setPosition(new LatLng(lat, lng)); if (t < 1.0) { // Post again 16ms later. handler.postDelayed(this, 16); } else { if (hideMarke) { m.setVisible(false); } else { m.setVisible(true); } } } }); } 

Aquí está mi código para mover marcador como uber. He mostrado dos maneras de mover el marcador.

Nota importante: Para mover el coche en la carretera adecuada [como ola, uber] que necesita para utilizar la carretera api proporcionado por google

1. Por latitud y longitud estáticas

2.By Tiempo real Latitud y longitud

 package com.gangsofcoder.googlemapdemo; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.location.Location; import android.location.LocationManager; import android.os.Bundle; import android.os.Handler; import android.os.PersistableBundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.animation.LinearInterpolator; import android.widget.Button; import android.widget.Toast; 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.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import com.loopj.android.http.AsyncHttpResponseHandler; import com.loopj.android.http.RequestParams; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import cz.msebera.android.httpclient.Header; public class MoveCar extends AppCompatActivity { private GoogleMap googleMap; SupportMapFragment mapFragment; Marker marker; private boolean isMarkerRotating = false; ArrayList<LatLng> listOfPoints = new ArrayList<>(); int currentPt = 0; LatLng finalPosition; Marker mMarker; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setUpMapIfNeeded(); //new location details listOfPoints.add(new LatLng(30.701623, 76.684220)); listOfPoints.add(new LatLng(30.702486, 76.685487)); listOfPoints.add(new LatLng(30.703135, 76.684891)); listOfPoints.add(new LatLng(30.703256, 76.685000)); listOfPoints.add(new LatLng(30.703883, 76.685941)); listOfPoints.add(new LatLng(30.703413, 76.685190)); } private void setUpMapIfNeeded() { if (mapFragment == null) { mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); if (mapFragment != null) { mapFragment.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(GoogleMap googleMap) { loadMap(googleMap); } }); } } } private void loadMap(GoogleMap map) { googleMap = map; mMarker = googleMap.addMarker(new MarkerOptions().position(new LatLng(30.701623, 76.684220)).icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_car))); final Handler handler = new Handler(); //Code to move car along static latitude and longitude /* handler.postDelayed(new Runnable() { @Override public void run() { if (currentPt < listOfPoints.size()) { //post again Log.d("tess", "inside run "); Location targetLocation = new Location(LocationManager.GPS_PROVIDER); targetLocation.setLatitude(listOfPoints.get(currentPt).latitude); targetLocation.setLongitude(listOfPoints.get(currentPt).longitude); animateMarkerNew(targetLocation, mMarker); handler.postDelayed(this, 3000); currentPt++; } else { Log.d("tess", "call back removed"); //removed callbacks handler.removeCallbacks(this); } } }, 3000);*/ //Here move marker along real time updates final RequestParams params = new RequestParams(); params.put("source_lattitude", "lat"); params.put("source_longitude", "long"); params.put("date", "date"); //new handler handler.postDelayed(new Runnable() { @Override public void run() { LoopjHttpClient.post(getString(R.string.default_upload_website), params, new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { try { JSONObject jsonObject = new JSONObject(new String(responseBody)); String status = jsonObject.getString("status"); String text = jsonObject.getString("text"); //reading json array JSONArray jsonArray = jsonObject.getJSONArray("result"); String source = jsonArray.getJSONObject(0).getString("source"); String[] latLong = source.split(","); Location location = new Location(LocationManager.GPS_PROVIDER); location.setLatitude(Double.parseDouble(latLong[0])); location.setLongitude(Double.parseDouble(latLong[1])); //calling method to animate marker animateMarkerNew(location, mMarker); } catch (JSONException e) { e.printStackTrace(); } } @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { Log.d("onFailure", "onFailure"); } }); handler.postDelayed(this, 3000); } }, 3000); } private void animateMarkerNew(final Location destination, final Marker marker) { if (marker != null) { final LatLng startPosition = marker.getPosition(); final LatLng endPosition = new LatLng(destination.getLatitude(), destination.getLongitude()); final float startRotation = marker.getRotation(); final LatLngInterpolatorNew latLngInterpolator = new LatLngInterpolatorNew.LinearFixed(); ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1); valueAnimator.setDuration(3000); // duration 3 second valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { try { float v = animation.getAnimatedFraction(); LatLng newPosition = latLngInterpolator.interpolate(v, startPosition, endPosition); marker.setPosition(newPosition); googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder() .target(newPosition) .zoom(15.5f) .build())); marker.setRotation(getBearing(startPosition, new LatLng(destination.getLatitude(), destination.getLongitude()))); } catch (Exception ex) { //I don't care atm.. } } }); valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); // if (mMarker != null) { // mMarker.remove(); // } // mMarker = googleMap.addMarker(new MarkerOptions().position(endPosition).icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_car))); } }); valueAnimator.start(); } } private interface LatLngInterpolatorNew { LatLng interpolate(float fraction, LatLng a, LatLng b); class LinearFixed implements LatLngInterpolatorNew { @Override public LatLng interpolate(float fraction, LatLng a, LatLng b) { double lat = (b.latitude - a.latitude) * fraction + a.latitude; double lngDelta = b.longitude - a.longitude; // Take the shortest path across the 180th meridian. if (Math.abs(lngDelta) > 180) { lngDelta -= Math.signum(lngDelta) * 360; } double lng = lngDelta * fraction + a.longitude; return new LatLng(lat, lng); } } } //Method for finding bearing between two points private float getBearing(LatLng begin, LatLng end) { double lat = Math.abs(begin.latitude - end.latitude); double lng = Math.abs(begin.longitude - end.longitude); if (begin.latitude < end.latitude && begin.longitude < end.longitude) return (float) (Math.toDegrees(Math.atan(lng / lat))); else if (begin.latitude >= end.latitude && begin.longitude < end.longitude) return (float) ((90 - Math.toDegrees(Math.atan(lng / lat))) + 90); else if (begin.latitude >= end.latitude && begin.longitude >= end.longitude) return (float) (Math.toDegrees(Math.atan(lng / lat)) + 180); else if (begin.latitude < end.latitude && begin.longitude >= end.longitude) return (float) ((90 - Math.toDegrees(Math.atan(lng / lat))) + 270); return -1; } 

}

Finalmente escribió el código que funciona exactamente de la misma manera que OLA CABS hace …

Aquí está –

  1. Ponga su fragmento de Google Maps en un diseño Relativo y coloque el marcador (como vista de imagen) en el centro –

  2. En el código de tu fragmento una vez que hayas configurado todos los mapas básicos de google, escribe el siguiente código para la función onMapReady (GoogleMap googleMap)

Mi código es el siguiente –

//Paso 1 –

  <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MapsActivity_for_request_pages" /> <ImageView android:layout_width="30sp" android:layout_height="30sp" android:layout_centerInParent="true" android:id="@+id/central_marker" android:src="@drawable/marker_pic"/> </RelativeLayout> 

//Paso 2 –

 @Override public void onMapReady(GoogleMap googleMap) { central_marker = (ImageView)v.findViewById(R.id.central_marker); int init_loc = 0,final_loc = -300; mMap = googleMap; final CountDownTimer timer = new CountDownTimer(300,300) { @Override public void onTick(long millisUntilFinished) { } @Override public void onFinish() { init_loc = 0; ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(central_marker, "translationY", final_loc, init_loc); objectAnimatorY.setDuration(200); objectAnimatorY.start(); } }; mMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() { @Override public void onCameraMoveStarted(int i) { System.out.println("Camera started moving worked"); timer.cancel(); ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(central_marker, "translationY", init_loc, final_loc); objectAnimatorY.setDuration(200); objectAnimatorY.start(); init_loc = -300; } }); mMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() { @Override public void onCameraIdle() { System.out.println("Camera idle worked"); if(initial_flag!=0) { System.out.println("Camera Setting timer now"); timer.cancel(); timer.start(); } initial_flag++; System.out.println("Camera Value of initial_flag ="+initial_flag); } }); } 

UberCarAnimation es una biblioteca de Android que muestra el movimiento del coche en el mapa como en Uber.

API y bibliotecas que necesita ser utilizado para implementar la animación Uber Car:

  • Google Maps Api
  • API de direcciones de Google Maps
  • Voleo

Dime cómo

Analice el " overview_polyline " del JSON proporcionando los parámetros GET apropiados. Por ejemplo:

 "https://maps.googleapis.com/maps/api/directions/json?" + "mode=driving&" + "transit_routing_preference=less_driving&" + "origin=" + latitude + "," + longitude + "&" + "destination=" + destination + "&" + "key=" + getResources().getString(R.string.google_directions_key) 

Decodificar la polilínea que le proporcionará la lista de latitudes y longitudes que es Lista para ser apto.

Cree un animador de valor proporcionando el valor de ofFloatValue , estableciendo la duración y añadiendo el oyente de actualización en Handler

 ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1); valueAnimator.setDuration(3000); valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { //CODE }); 

En el animador de valor, el oyente de actualización obtiene la fracción Animación y evalúa las latitudes y longitudes como se muestra:

 v=valueAnimator.getAnimatedFraction(); lng = v * endPosition.longitude + (1 - v)* startPosition.longitude; lat = v * endPosition.latitude + (1 - v)* startPosition.latitude; 

Donde v es la fracción de animación y startposition y endPostion se refieren a cada par de LatLng de la lista decodificada de la polilínea por ejemplo (0,1) entonces (1,2) entonces (2,3) y así sucesivamente.

Finalmente establecer la posición del marcador a la nueva posición, también evaluar el cojinete entre los puntos consecutivos de modo que parece que el coche se está convirtiendo literalmente y finalmente actualizar la cámara como:

 marker.setPosition(newPos); marker.setAnchor(0.5f, 0.5f); marker.setRotation(getBearing(startPosition, newPos)); mMap.moveCamera(CameraUpdateFactory .newCameraPosition (new CameraPosition.Builder() target(newPos) .zoom(15.5f) .build())); 

La aplicación utiliza la clave Api de Google Maps y la clave de direcciones de Google Map. Obtenga esta clave de api en la consola de desarrolladores de Google después de habilitarlos para su proyecto. Reemplace las claves api de google maps directions en strings.xml y google maps key en google_maps_api.xml.

Esta es una implementación básica de Location Tracker con Google Maps API, implementa el Listener de ubicación para obtener actualizaciones periódicas de movimientos y anima el puntero de mapa similar a la Uber App.

Introduzca aquí la descripción de la imagen

https://github.com/frankodoom/MotionVehicleTracker

  • Ancho del elemento RecyclerView layout_width = "match_parent" no coincide con el padre
  • Tratar de que Android LinearLayout se estire horizontal y verticalmente
  • Edición de Edición personalizada de Android y NextFocusDown
  • RadioGroup checkedButton propiedad
  • Botón - Cambiar el color de fondo al hacer clic
  • Manifiesto de Android que genera automáticamente permiso no válido
  • Cómo hacer que Android soporte FloatingActionButton en la parte inferior derecha de la pantalla?
  • Html a xml (análisis sintáctico)
  • Cómo hacer referencia a programación <string> en archivo xml en android
  • El desplazamiento de texto no funciona
  • Utilizar el prefijo de Android en xml (android :, app :, @ .., ...)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.