Del diseño a Android, parte 2

Ha pasado mucho tiempo desde mi publicación anterior, muchas cosas han sucedido desde entonces, pero finalmente está aquí. ¡Espero que lo disfruten!.

Esta es una nueva historia en mi serie de artículos llamada 'Del diseño a Android', si recuerdas la primera parte de estas series, elijo un concepto de diseño que me parece interesante y trato de implementarlo en Android, centrándome en algunos interesantes temas en el camino desde mi perspectiva de desarrollador de Android.

Todo el código referido en esta publicación se puede encontrar en el repositorio de Github

Este es el concepto que he elegido para esta parte:

Google business - Slider de Johny Vino

Utilicé una vez más un concepto proveniente de Johny Vino.

Intenta detenerte por un segundo para descubrir, como desarrollador de Android como eres, cómo hacer una implementación de esa pantalla.

Si descubriste dos de los siguientes puntos, tal vez estuviste de acuerdo conmigo, a primera vista, me vinieron a la mente dos partes:

  • Cómo implementar la animación del edificio, por supuesto.
  • Esa barra de búsqueda podría no ser tan trivial como debería ser

Animando el edificio

Pongamos este ejercicio en un entorno perfecto, podemos pedir a nuestros diseñadores que creen la animación. Después de quizás, algunos After Effects funcionan + el complemento de Bodymovin, podrían darnos el vector animado deseado que se puede dibujar.

O ..., es posible que no tengamos ningún diseñador, y usted es un desarrollador valiente y solitario que necesita hacerlo sin muchas habilidades de diseño, intentemos ese camino.

Trabajando con vectores

Con un poco de trabajo en una herramienta basada en vectores como Sketch o BoxySvg, podríamos vectorizar fácilmente la imagen del edificio. Agrupar aquellas partes que se animarán en grupos será útil para el siguiente punto.

Crear la imagen deseada en Sketch

A continuación, una nueva herramienta increíble llega a la escena, y esta es Shape Shifter, de Alex Lockwood. Esta increíble herramienta te ayuda a animar imágenes basadas en SVG y a exportar esas animaciones a un AVD entre otros formatos.

Cambiador de forma

Después de crear el efecto deseado en unos pocos clics, podemos exportar nuestro nuevo dibujo animado vectorial dibujable, pegarlo en Android Studio, vincularlo a un ImageView y listo.

(img_building.drawable como Animatable) .start ()
El AVD de ShapeFilter exportado se ejecuta en un dispositivo Android

Sí, increíble, ¿verdad? Acabamos de crear una gran animación sin esfuerzo, pero, si volvemos a ver el concepto de Johny Vino, nos hemos perdido pequeños detalles. La animación se maneja mediante una barra deslizante (conocida como Seekbar en Android) que maneja el estado de la animación dependiendo del progreso de la barra.

Entonces, lo que necesitamos es hasta ahora establecer el progreso de la animación dentro de un AVD. Bueno ... actualmente eso no es compatible con lo que he visto (Lottie sí). Solo tenemos a nuestra disposición métodos como .start (), .stop () y reset ().

En este punto podríamos intentar lo siguiente:

O continúe, iteremos solo un poco más.

Selecciones animadas dibujables

En nuestro punto actual, tenemos una animación que debe ser ordenada para ir a un cuadro específico cuando el SeekBar alcanza una posición específica. En otras palabras, tenemos algunos estados durante la animación.

Declaremos algunos atributos para definir estos marcos o estados.


    
    
    
    
    
    

En este punto, permítanme presentarles un dibujable quizás no muy conocido, el AnimatedStateListDrawable que nos salvará totalmente el día.

Consulte la documentación de Android:

Drawable que contiene un conjunto de fotogramas clave Drawable donde el fotograma clave que se muestra actualmente se elige en función del conjunto de estado actual. Las animaciones entre fotogramas clave pueden definirse opcionalmente utilizando elementos de transición.
Este dibujo se puede definir en un archivo XML con el elemento . Cada fotograma clave Drawable se define en un elemento anidado. Las transiciones se definen en un elemento anidado.

Parece un poco lo que estamos buscando, ¿verdad? Podríamos definir algunos que identificarán los diferentes cuadros en nuestra animación y las transiciones sobre cómo hacer la transición de un elemento a otro.

Como cada etiqueta representaría nuestro marco, definiremos tres de ellas, cada una compuesta por un vector dibujable.

drawable / vd_building1.xml
drawable / vd_building2.xml
drawable / vd_building3.xml

Y cada representará cómo un pasa a otro, necesitaremos 4 para hacer la transición a través de todos los fotogramas de un lado a otro.

Con el Shape Shifter mencionado anteriormente, podemos exportar fácilmente los AVD requeridos a Android Studio, que funcionarán como transiciones en AnimationStateListDrawable.

drawable / avd_building_1_2
drawable / avd_building_2_3
drawable / avd_building_3_2
drawable / avd_building_2_1
avd_building_1_2.xmlavd_building_2_3.xml

Y finalmente todo el AnimatedStateDrawable que acabamos de construir:




    

    

    

    

    

    

    

Ajustando un poco nuestra actividad y nuestro diseño, configuramos este increíble AnimatedSelectorDrawable en un ImageView como recurso fuente, y haciendo uso del método setImageState con el estado deseado, la animación funcionará mágicamente como se esperaba.

val privado STATE_ZERO = intArrayOf (
        R.attr.state_zero, -R.attr.state_one, -R.attr.state_two
)

valor privado STATE_ONE = intArrayOf (
        -R.attr.state_zero, R.attr.state_one, -R.attr.state_two
)

val privado STATE_TWO = intArrayOf (
        -R.attr.state_zero, -R.attr.state_one, R.attr.state_two
)
diversión privada enSeekProgressChanged (posición: Int) {
    val max = seekbar.max

    val businessType = when (position) {
        en 0..max / 3 -> STATE_ZERO
        en 10..max / 2 -> STATE_ONE
        en 20..max / 1 -> STATE_TWO
        de lo contrario -> lanzar IllegalStateException ()
    }

    imageView.setImageState (businessType, true)
}

Resultado:

Animando el pulgar de Seekbar

Yai! Hasta ahora, hemos alcanzado uno de mis dos puntos calientes, el segundo es administrar cómo animar el tamaño del pulgar Seekbar durante el progreso, como lo hace Johny Vino en su concepto:

Tamaño del pulgar de Seekbar al arrastrar

Podemos distinguir dos comportamientos aquí:

  • El tamaño del pulgar se está incrementando de alguna manera relacionado con el progreso
  • Al lanzar, se está realizando una especie de animación de rebasamiento

Una visita al ScaleDrawable

Otro dibujable desconocido (al menos para mí) es el ScaleDrawable, volvamos a consultar la documentación de Android:

Un Drawable que cambia el tamaño de otro Drawable en función de su valor de nivel actual. Puede controlar cuánto cambia el niño Drawable en ancho y altura según el nivel, así como una gravedad para controlar dónde se coloca en su contenedor general. La mayoría de las veces se usa para implementar cosas como barras de progreso.
El nivel predeterminado se puede especificar desde XML utilizando la propiedad android: level. Cuando no se especifica esta propiedad, el nivel predeterminado es 0, que corresponde a cero altura y / o ancho dependiendo de los valores especificados para android.R.styleable # ScaleDrawable_scaleWidth scaleWidthand android.R.styleable # ScaleDrawable_scaleHeight scaleHeight. En tiempo de ejecución, el nivel puede establecerse mediante setLevel (int).

Entonces, parece que podríamos definir algún tipo de dibujable que haga referencia a otro dibujable, un nivel y un factor de escala. Si adjuntamos el progreso de la barra a ese nivel, debería funcionar, ¿no ?.

Definamos una lista de capas de elementos dibujables y, dado que solo queremos que la parte azul se escale, la envolveremos en un ScaleDrawable.



    
        

            
              
                  

                  
              
            
        
    
    
        
            
        
    

Como puede ver, usando la herramienta podemos incorporar los atributos requeridos directamente en

thumb <layer-list> que contiene un ScaleDrawable

Ahora solo tenemos que ajustar nuevamente nuestra actividad para establecer el nivel de ScaleDrawable, justo cuando cambia el progreso de SeekBar, observe también qué bueno es que podemos usar la propiedad de nivel desde el Drawable del pulgar.

diversión privada enSeekProgressChanged (posición: Int) {
    // ...
    
    ((seekbar.thumb como LayerDrawable)). level =
            (posición * (SCALE_MAX / seekbar.max))
}

Y el resultado:

Ahora solo tenemos que animar el pulgar al soltar, podemos deshacernos de eso haciendo uso de ScaleDrawable y ValueAnimator.

diversión privada animateThumbRelease () {
    val thumb = seekbar.thumb
    val initLevel = thumb.level
    val maxLevel = thumb.level * THUMB_RELEASE_SCALE_FACTOR
    val animator = ValueAnimator.ofInt (
            initLevel, maxLevel, initLevel)

    con (animador) {
        interpolador = RESULTADO
        duración = THUMB_SCALE_DURATION

        addUpdateListener {
            thumb.level = it.animatedValue como Int
        }

        comienzo()
    }
}

Resultado:

Terminando

En este punto, hemos resuelto el problema con la animación, y luego con la Seekbar, con algunas modificaciones más triviales como crear un AVD para las nubes en movimiento, usar la nueva fuente como capacidad de recursos para nuestros textos y agregar Como nuevo ícono adaptativo, tenemos algo bastante similar al concepto de Johny Vino.

Espero que hayas disfrutado durante el camino y, si tienes que matarme por algo, hazlo con un bonito comentario y un emoji agresivo.

Resultado final:

Repositorio Github

aquí

Referencias

  • VectorDrawable Adaptive Icons, Ian Lake
  • Diseño de iconos adaptativos, Nick Butcher
  • Cambiaformas, Alex Lockwood
  • Una introducción a las técnicas de animación de iconos, Alex Lockwood
  • adp-deliciousful-details, Alex Lockwood
  • Cómo diseñamos una hermosa animación, Jeremie Martinez