¿Cómo agregar Uber Car Animation en la aplicación de Android?

Google Map se está utilizando en muchas aplicaciones en estos días. Muchas aplicaciones necesitan los servicios de Google Maps para múltiples propósitos. Un ejemplo de tales aplicaciones son nuestras aplicaciones de la vida diaria como Zomato, Swiggy y Amazon que usan Google Maps para fines de entrega, mientras que aplicaciones como Uber y ola usan mapas para rastrear la ubicación en tiempo real del pasajero y el conductor. En todos los ejemplos anteriores ha sido Visto que aparecen varios tipos de animaciones en las líneas de mapeo, como en Uber, se muestra un automóvil para rastrear la ubicación del conductor y se muestra en la pantalla del cliente. En este artículo, veremos cómo agregar esas animaciones en Android con Google Maps. .

  • Primeros pasos con la plataforma de Google Maps
  • Integrando google maps con android
  • Adición de animaciones en mapas

Primeros pasos con la plataforma de Google Maps

Paso 1: vaya a https://console.developers.google.com/ y haga clic en el botón desplegable del proyecto y seleccione un proyecto o cree uno.

Paso 2: haga clic en el botón de menú que se encuentra en la parte superior izquierda del sitio web, luego seleccione API y servicios, luego aparecerá otra lista desplegable, desde allí seleccione las credenciales.

Paso 3: una vez que esté en la página de credenciales, haga clic en el botón «Crear credenciales», luego haga clic en la clave API y luego aparecerá una ventana emergente que muestra la clave API. Asegúrese de copiar y pegar la clave API en el bloc de notas o algo así.

Paso 4: Ahora regrese a la pestaña API y servicios y haga clic en el botón «Biblioteca», luego busque Google Map SDK para Android y luego haga clic en habilitar.

Integrando google maps con android

Paso 1: Crear un nuevo proyecto 

Para crear un nuevo proyecto en Android Studio, consulte Cómo crear/iniciar un nuevo proyecto en Android Studio . Tenga en cuenta que seleccione Kotlin como lenguaje de programación.

Paso 2: actualice el archivo de manifiesto de Android

Vaya al archivo AndroidManifests.xml y agregue el siguiente código dentro de la etiqueta <application>. Recuerde que copiamos la clave API, asegúrese de pegarla a continuación como se muestra a continuación.

XML

<application>
    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="API_KEY" />
</application>

Paso 3: Agregar fragmento de mapas de Google en el archivo activity_main.xml

Agregaremos el fragmento de mapa de Google dentro del cual se mostrará el mapa. Elimine todo el código en activity_main.xml antes de agregar el código a continuación

XML

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" />

Paso 4: Configurar el mapa de Google en el archivo MainActivity

Simplemente defina el fragmento de Google Map e implemente la interfaz OnMapReadyCallBack y anule la función onMapReady() como se muestra a continuación

Kotlin

class MainActivity : AppCompatActivity(), OnMapReadyCallback {
  
    private lateinit var googleMap: GoogleMap
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val map = supportFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment
        map.getMapAsync(this)
    }
  
    override fun onMapReady(googleMap: GoogleMap) {
        this.googleMap = googleMap
    }

Paso 5: muestra la ubicación predeterminada en el mapa

De forma predeterminada, el mapa puede mostrar cualquier posición aleatoria, pero podemos mostrar la ubicación como queramos. En este proyecto, usaremos la ubicación LatLng (28.435350000000003, 77.11368) como ubicación predeterminada, cuando se inicie la aplicación. Entonces, necesitamos hacer dos funciones moveCamera() y animateCamera(). El método moveCamera() se usará para reposicionar la cámara a cierta latitud y longitud. Mientras que el método animateCamera() se usará para animar el movimiento de la cámara desde la posición actual a una nueva posición. 

Kotlin

private fun moveView(ll: LatLng) {
       googleMap.moveCamera(CameraUpdateFactory.newLatLng(ll))
   }
 
   private fun animateView(ll: LatLng) {
       val cameraPosition = CameraPosition.Builder().target(ll).zoom(15.5f).build()
       googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
   }

Haz otra función showDefaultLocaitonOnMap() y llámala dentro de onMapReady().

private fun displayDefaultLocation(ll: LatLng) {
        moveView(ll)
        animateView(ll)
  }

Kotlin

private lateinit var defaultLocation: LatLng
  
override fun onMapReady(googleMap: GoogleMap) {
    this.googleMap = googleMap
    defaultLoc = LatLng(28.435350000000003, 77.11368)
    displayDefaultLocation(defaultLoc)
}

Paso 6: Creación de Utilidades

Cree dos nuevos archivos de objetos de Kotlin, 

  • MapUtils.kt 
  • AnimationUtils.kt

Paso 7: trabajar con el archivo MapUtils

En nuestro proyecto, usaremos algunos valores codificados de LatLng. Entonces, en la clase MapUtils, creemos una función getLocations() que devolverá una lista de LatLng que corresponderá a una ruta.

Kotlin

fun getLocations(): ArrayList<LatLng> {
       val locationList = ArrayList<LatLng>()
       locationList.add(LatLng(28.4356, 77.11498))
       locationList.add(LatLng(28.435660000000002, 77.11519000000001))
       locationList.add(LatLng(28.43568, 77.11521))
       locationList.add(LatLng(28.436580000000003, 77.11499))
       locationList.add(LatLng(28.436590000000002, 77.11507))
       locationList.add(LatLng(28.436970000000002, 77.11272000000001))
       locationList.add(LatLng(28.43635, 77.11289000000001))
       locationList.add(LatLng(28.4353, 77.11317000000001))
       locationList.add(LatLng(28.435280000000002, 77.11332))
       locationList.add(LatLng(28.435350000000003, 77.11368))
       return locationList
   }

Ahora, tenemos una lista de LatLng y con la ayuda de LatLng, podemos dibujar un camino entre el Origen y el Destino. Ahora crearemos una función getStartingLocationBitmap() que devolverá un mapa de bits. La función será la siguiente.

Kotlin

fun getStartingLocationBitmap(): Bitmap {
       val height = 40
       val width = 40
       val bitmap = Bitmap.createBitmap(height, width, Bitmap.Config.RGB_565)
       val canvas = Canvas(bitmap)
       val paint = Paint()
       paint.color = Color.BLACK
       paint.style = Paint.Style.FILL
       paint.isAntiAlias = true
       canvas.drawRect(0F, 0F, width.toFloat(), height.toFloat(), paint)
       return bitmap
   }

Ahora crea una nueva función llamada getCarRotation() que toma dos ubicaciones, es decir, inicio y final y luego devuelve el ángulo entre ellos, desde el ángulo que devolverá determinaremos cómo se debe dirigir el ícono del automóvil.

Kotlin

fun getCarRotation(startLL: LatLng, endLL: LatLng): Float {
       val latDifference: Double = abs(startLL.latitude - endLL.latitude)
       val lngDifference: Double = abs(startLL.longitude - endLL.longitude)
       var rotation = -1F
       when {
           startLL.latitude < endLL.latitude && startLL.longitude < endLL.longitude -> {
               rotation = Math.toDegrees(atan(lngDifference / latDifference)).toFloat()
           }
           startLL.latitude >= endLL.latitude && startLL.longitude < endLL.longitude -> {
               rotation = (90 - Math.toDegrees(atan(lngDifference / latDifference)) + 90).toFloat()
           }
           startLL.latitude >= endLL.latitude && startLL.longitude >= endLL.longitude -> {
               rotation = (Math.toDegrees(atan(lngDifference / latDifference)) + 180).toFloat()
           }
           startLL.latitude < endLL.latitude && startLL.longitude >= endLL.longitude -> {
               rotation =
                   (90 - Math.toDegrees(atan(lngDifference / latDifference)) + 270).toFloat()
           }
       }
       return rotation
   }

Cada función mencionada anteriormente irá dentro del archivo MapUtils.

Paso 8: trabajar con el archivo AnimationUtils

Cree dos funciones polyAnimator() y carAnimator que devolverán un valor de interpolador como se muestra a continuación

Kotlin

fun polyAnimator(): ValueAnimator {
        val valueAnimator = ValueAnimator.ofInt(0, 100)
        valueAnimator.interpolator = LinearInterpolator()
        valueAnimator.duration = 4000
        return valueAnimator
    }
  
    fun carAnimator(): ValueAnimator {
        val valueAnimator = ValueAnimator.ofFloat(0f, 1f)
        valueAnimator.duration = 3000
        valueAnimator.interpolator = LinearInterpolator()
        return valueAnimator
    }

Paso 9: Trabajar con MainActivity

Cree dos nuevas funciones getCarMarker() y getOrigonMarker() que devolverán un objeto de marcador, se usará en Actualizar ubicación del automóvil. Cree las funciones como se muestra a continuación.

Kotlin

private fun getCarMarker(ll: LatLng): Marker {
     val bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(MapUtils.getBitmap(this))
     return googleMap.addMarker(
         MarkerOptions().position(ll).flat(true).icon(bitmapDescriptor)
     )
 }
 
 private fun getOriginMarker(ll: LatLng): Marker {
     val bitmapDescriptor =
         BitmapDescriptorFactory.fromBitmap(MapUtils.getStartingLocationBitmap())
     return googleMap.addMarker(
         MarkerOptions().position(ll).flat(true).icon(bitmapDescriptor)
     )
 }

Ahora crea una función llamada displayPath() que tomará una lista de LatLng y esta función se usará para dibujar una ruta entre el origen y el destino.

Kotlin

private fun displayPath(latLngList: ArrayList<LatLng>) {
        val builder = LatLngBounds.Builder()
        for (latLng in latLngList) {
            builder.include(latLng)
        }
        val boundBuilds = builder.build()
        googleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(boundBuilds, 2))
  
        val polyOptions = PolylineOptions()
        polyOptions.color(Color.GRAY)
        polyOptions.width(5f)
        polyOptions.addAll(latLngList)
        greyLine = googleMap.addPolyline(polyOptions)
  
        val blackPolyOptions = PolylineOptions()
        blackPolyOptions.color(Color.BLACK)
        blackPolyOptions.width(5f)
        blackLine = googleMap.addPolyline(blackPolyOptions)
  
        oMarker = getOriginMarker(latLngList[0])
        oMarker?.setAnchor(0.5f, 0.5f)
        dMarker = getOriginMarker(latLngList[latLngList.size - 1])
        dMarker?.setAnchor(0.5f, 0.5f)
  
        val polyAnimator = AnimationUtils.polyAnimator()
        polyAnimator.addUpdateListener { valueAnimator ->
            val precent = (valueAnimator.animatedValue as Int)
            val indexNumber = (greyLine?.points!!.size) * (precent / 100.0f).toInt()
            blackLine?.points = greyLine?.points!!.subList(0, indexNumber)
        }
        polyAnimator.start()
    }

Cree la función updateCarLoc() que verificará si el automóvil se está moviendo o no y si el automóvil aún no se está moviendo, esta función hará que el automóvil se mueva.

Kotlin

private fun updateCarLoc(ll: LatLng) {
        if (movingMarker == null) {
            movingMarker = getCarMarker(ll)
        }
        if (previousLL == null) {
            currentLL = ll
            previousLL = currentLL
            movingMarker?.position = currentLL
            movingMarker?.setAnchor(0.5f, 0.5f)
            animateView(currentLL!!)
        } else {
            previousLL = currentLL
            currentLL = ll
            val valueAnimator = AnimationUtils.carAnimator()
            valueAnimator.addUpdateListener { va ->
                if (currentLL != null && previousLL != null) {
                    val multiplier = va.animatedFraction
                    val nxtLoc = LatLng(
                        multiplier * currentLL!!.latitude + (1 - multiplier) * previousLL!!.latitude,
                        multiplier * currentLL!!.longitude + (1 - multiplier) * previousLL!!.longitude
                    )
                    movingMarker?.position = nxtLoc
                    val rotation = MapUtils.getCarRotation(previousLL!!, nxtLoc)
                    if (!rotation.isNaN()) {
                        movingMarker?.rotation = rotation
                    }
                    movingMarker?.setAnchor(0.5f, 0.5f)
                    animateView(nxtLoc)
                }
            }
            valueAnimator.start()
        }
    }

Finalmente, cree la función mostrarCocheEnMovimiento() dentro de la cual llamaremos a actualizarCarroLoc() hasta el punto final de la ubicación. También usaremos un controlador para mostrar un retraso.

Kotlin

private fun displayMovingCar(cabLatLngList: ArrayList<LatLng>) {
       myHandler = Handler()
       var index = 0
       myRunnable = Runnable {
           run {
               if (index < 10) {
                   updateCarLoc(cabLatLngList[index])
                   myHandler.postDelayed(myRunnable, 3000)
                   ++index
               } else {
                   myHandler.removeCallbacks(myRunnable)
                   Toast.makeText(this@MainActivity, "Trip Ends", Toast.LENGTH_LONG).show()
               }
           }
       }
       myHandler.postDelayed(myRunnable, 5000)
   }

Producción: 

En la salida podemos ver un coche en movimiento de un punto a otro.

Output

Publicación traducida automáticamente

Artículo escrito por shekharshinde9990 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *