En este capítulo empezaremos a pintar en el mapa, y para ello vamos a empezar con lo más sencillo, las polylines.

Polylines en Google Maps

Estas polylines son simplemente líneas que podemos dibujar en el mapa para trazar rutas, seleccionar una parte del mapa o lo que se te ocurra. Y obviamente todo esto lo podremos personalizar.

Let’s code!

Para esta tercera parte vamos a seguir con el proyecto de los capítulos anteriores así que si acabas de llegar te recomiendo que eches un ojo a la primera parte y segunda parte.

Ahora piensa, si queremos dibujar una polyline en el mapa que es básicamente una línea la forma de hacerlo será a través de coordenadas. Es como añadir un marker pero con un listado de coordenadas.

    private fun createPolylines(){
        val polylineOptions = PolylineOptions()
            .add(LatLng(40.419173113350965,-3.705976009368897))
            .add(LatLng( 40.4150807746539, -3.706072568893432))
            .add(LatLng( 40.41517062907432, -3.7012016773223873))
            .add(LatLng( 40.41713105928677, -3.7037122249603267))
            .add(LatLng( 40.41926296230622,  -3.701287508010864))
            .add(LatLng( 40.419173113350965, -3.7048280239105225))
            .add(LatLng(40.419173113350965,-3.705976009368897))

        val polyline = map.addPolyline(polylineOptions)
    }

Analicemos el código anterior. Yo he creado una función que contiene un PolylineOptions(), este objeto va a recibir una cantidad N de objetos LatLng que son básicamente coordenadas. Cuando ya tenemos nuestras coordenadas añadidas solo tenemos que avisar a nuestro map con la función addPolyline() y pasarle nuestro PolylineOptions().

El resultado de esa operación lo estoy almacenando en una variable llamada polyline, ya que cuando añadimos un PolyLineOptions en el mapa, este ya se convierte en un objeto Polyline.

Ahora para que se carguen dichas líneas tendremos que llamar a la función que acabamos de crear desde onMapReady que será el método que se ejecuta al cargar el mapa.

  override fun onMapReady(googleMap: GoogleMap) {
        map = googleMap
        createPolylines()
        ...
        ...
    }

Ejecuta la app.

Mostrando nuestra primera Polyline.

He intentado dibujar con coordenadas el logo de Kotlin.

Ahora la siguiente duda que te habrá llegado posiblemente es como sacar esas coordenadas ¿Verdad? Pues tenemos infinidad de formas, pero para mi la forma más sencilla es usar GeoJson IO. Si quieres saber como lo uso yo puedes verlo en el capítulo en vídeo que he dejado en la parte superior.

Personalizar Polylines

Como comenté al principio, podremos personalizar nuestras polyline bastante así que lo primero que haremos será aumentar el grosor de la línea. Para ello justo después de añadir las coordenadas que pusimos anteriormente, añadiremos el atributo width() con un float en el interior que definirá el tamaño que por defecto es 10f.

También quiero modificar el color de esa línea, ya que estoy intentando crear el logo de Kotlin, vamos a ponerlo con un tono violeta.

Para añadirle un color tendremos que hacer dos cosas, la primera es ir al fichero Colors.xml (dentro de res>Values) y añadir el nuevo color.

    <color name="kotlin">#A802EF</color>

Ahora ya podremos usar el atributo color justo después del width.

    private fun createPolylines(){
        val polylineOptions = PolylineOptions()
            .add(LatLng(40.419173113350965,-3.705976009368897))
            .add(LatLng( 40.4150807746539, -3.706072568893432))
            .add(LatLng( 40.41517062907432, -3.7012016773223873))
            .add(LatLng( 40.41713105928677, -3.7037122249603267))
            .add(LatLng( 40.41926296230622,  -3.701287508010864))
            .add(LatLng( 40.419173113350965, -3.7048280239105225))
            .add(LatLng(40.419173113350965,-3.705976009368897))
            .width(30f)
            .color(ContextCompat.getColor(this, R.color.kotlin))


        val polyline = map.addPolyline(polylineOptions)
    }
ejemplo-polyline-con-colores-y-tamaño
Polyline personalizada.

Personalizar bordes en Polylines

Para explicarte esta parte voy a borrar la última de las coordenadas para que nuestra línea no cierre. Y esto lo hago porque quiero que veas que si ejecutas ahora la línea terminará de una forma muy «brusca» y lo podemos mejorar. Para ello utilizaremos los atributos cap que nos permitirá redondear el principio o el final e incluso añadir imágenes.

En esta ocasión no añadiremos los caps justo después de las coordenadas como el color y el tamaño, aquí tendremos que usar el polyline que almacenamos al añadir el PolyOptions al mapa.

polyline.startCap = RoundCap()
polyline.endCap = CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.hexagram))

Aunque sean dos líneas hay mucho que explicar. Para empezar, podemos personalizar el inicio y el fin de forma independiente a través de startCap y endCap. Al inicio le he puesto RoundCap() que es simplemente el borde redondeado. Al final le he añadido una imagen que tenía en mi carpeta drawable.

Es importante que recuerdes que este método no soporta vectores, es decir, si quieres usar una imagen tiene que ser en formato png.

antes y despues de redondear bordes
Con bordes y sin bordes.

Patrones en Polylines

Si te fijas en cualquiera de los ejemplos anteriores, la linea siempre es igual, es decir, mas ancha o mas delgada pero siempre es igual. En esta ocasión te hablaré sobre los patrones.

Un pattern nos permite definir el trazo de nuestra polyline a través de tres atributos.

  • Dot: Un simple punto.
  • Dash: Un guión al cual habrá que pasarle la longitud en float.
  • Gap: Un espacio que también recibirá la longitud en float.

Lo verás mejor ahora.

     val pattern = listOf(
            Dot(), Gap(10F), Dash(50F), Gap(10F)
        )
        polyline.pattern = pattern

Fíjate que he creado una lista en la cual he metido mi patrón. Según la lista anterior será un punto, un espacio de 10, un guión de 50 y otro espacio de 10. Luego a mi polyline se lo añado y se repetirá dicho patrón durante toda la línea.

ejemplo patron en polyline
Pattern en Polyline

Obviamente este patrón lo he creado yo pero puedes ir jugando con esos tres objetos para crear tu patrón perfecto.

Polylines clickables

Nuestras líneas también pueden ser clickables aunque por defecto no lo sean. Para ello lo primero que haremos será añadirle el atributo clickable a true a nuestra polyline.

        polyline.isClickable = true
  
        map.setOnPolylineClickListener {  }

Una vez hecho eso, le pondremos un listener a nuestro mapa para que nos avise cuando una polyline ha sido pulsada.

Dentro de ese listener ya podemos hacer lo que queramos, por ejemplo cambiar el color de la línea de forma aleatoria. Para ello crearemos un método llamado changeColor().

   fun changeColor(polyline: Polyline){
        val color = (0..3).random()
        when(color){
            0 -> polyline.color = ContextCompat.getColor(this, R.color.red)
            1 -> polyline.color = ContextCompat.getColor(this, R.color.yellow)
            2 -> polyline.color = ContextCompat.getColor(this, R.color.green)
            3 -> polyline.color = ContextCompat.getColor(this, R.color.blue)
        }
    }

Esta función que recibe la polyline a cambiar lo primero que hará será generar un número aleatorio entre el 0 y el 3, luego haremos un when donde a la polyline le asignaremos uno de los cuatro colores que he creado en el fichero colors.xml.

Ahora solo tenemos que llamar a esta función desde el listener que creamos antes.

        map.setOnPolylineClickListener { changeColor(it) }

Hasta aquí esta tercera parte, si te gustaría que cree un proyecto en GitHub con todo el código de los capítulos de Google Maps déjame un comentario.

También te recuerdo que si prefieres verlo de una forma más interactiva tienes el capítulo en vídeo en Youtube.

Continúa con el curso: Capítulo 38 – MVVM en Android con Kotlin – Implementando Retrofit, corrutinas y Clean Architecture


Te recuerdo que puedes seguirme en mis redes sociales en Aristi.Dev. Y si tienes dudas con este o cualquier otro artículo del blog únete al Discord de la comunidad y te ayudaremos.