Efecto Parallax con SensorManager con Jetpack Compose | de Suraj Sau | mayo 2022

Alessio Soggetti・UnsplashRecientemente, la implementación de Philip Davis del sorprendente efecto de paralaje en SwiftUI hizo las rondas de la comunidad de Android. Así que decidí implementarlo con Jetpack Compose en su lugar. Los resultados fueron bastante decentes y también fueron bien recibidos por nuestra encantadora comunidad de Twitter de Android. 😁La siguiente explicación se basa completamente en este núcleo.

Contenidos

Se recuperan los datos del sensor

Las vistas @Composable se reposicionan según la orientación del dispositivo. Y necesitamos los valores de orientación a lo largo del eje ‘pitch’ y ‘roll’.Hice referencia a esta respuesta de StackOverflow para mi implementación de obtener los valores de cabeceo y balanceo. Escuche los cambios del sensor para obtener cabeceo y balanceo

Registrar oyentes de SensorManager

Con DesechableEffect inicializamos SensorManager y también registramos oyentes para los sensores GRAVITY y MAGNETIC_FIELD. Finalmente, cabeceo y balanceo se reciben en @Composable con Channel.receiveAsFlow().collect() . Inicializar SensorManager en un DesechableEffectWrapper para nuestra implementación de SensorManager Se podría decir que podríamos haber usado LaunchedEffect en su lugar, ya que solo estamos recopilando el flujo de datos de nuestro sensor. Explicaré por qué terminé eligiendo un efecto desechable (tiene algo que ver con onDispose{}). Ahora que tenemos los valores de cabeceo y balanceo de nuestro sensor, ahora veremos cómo podemos reposicionar diferentes vistas de @Composable para lograr el efecto de paralaje. El propio Philip Davis señaló gentilmente su implementación:

  • Reposicionamiento de la tarjeta de imagen
  • Reposicionamiento de Glow Shadow (reverso de la tarjeta). Usé la implementación Philips Glow Shadow como referencia para esto.
  • muestra un borde de mapa sutil cuando se inclina para el efecto 3D pronunciado
  • Adición de paralaje a la imagen interior (reverso de la tarjeta)

Mostrar instrucciones de reposicionamiento basadas en la dirección del título

tarjeta de cara

Implementación de la tarjeta de imagen[1] Usamos Modifier.offset para reposicionar nuestras vistas @Composable.[2] El balanceo está a lo largo del eje y, mientras que el tono está a lo largo del eje x. Entonces, el desplazamiento x está determinado por el balanceo, mientras que el desplazamiento y está determinado por el tono.[3] Aplicamos el efecto de paralaje a la imagen interior ajustando el parámetro de alineación horizontalBias de @Composable Image().Movimiento del mapa de imágenes a lo largo de la orientación inclinada del dispositivo

sombra brillante

Implementación de Glow Shadow[1] El desplazamiento de Glow Shadow se reposiciona más rápido que el mapa de imagen y en la dirección opuesta.[2] Es más pequeño que la tarjeta de la cara.

  • Cuando el dispositivo se sostiene sobre una superficie plana (todos los valores de alineación cercanos a 0), la sombra brillante no debería ser visible.
  • La parte más oscura de las sombras es generalmente más pequeña que el objeto real.

[3] En lugar de usar una sombra tradicional, use Modifier.blur() para hacer que el mapa de la imagen parezca translúcido, permitiendo que la luz caiga sobre la superficie.Movimiento Glow Shadows junto con la tarjeta de cara.

borde de la tarjeta

Implementación de borde de tarjeta[1] El reposicionamiento de desplazamiento de Card Edge será un poco más florido que el de Image Card.

  • El borde no debe ser visible cuando se almacena en una superficie plana.
  • El borde debe ser «recto» visible cuando el dispositivo está inclinado para dar la apariencia de un mapa 3D delgado.

[2] El tamaño corresponde a la tarjeta de imagen.El movimiento del borde de la carta junto con la cara de la carta.

Anular el registro Cancelar la obtención de datos del sensor en AvailableEffect.onDispose{..}

Necesitamos evitar fugas innecesarias de SensorManager cuando esta vista se elimine de la composición. Es por eso que usé DisposeEffect en lugar de LaunchedEffect, porque obtenemos esta útil devolución de llamada de Dispose{} que podemos usar para limpiar cualquier dato innecesario al salir de la composición.

Use el método Modifier.offset correcto

Jetpack Compose ofrece dos tipos de modificadores de compensación:

  • .desplazamiento(x: Dp = 0.dp, y: Dp = 0.dp)
  • .offset(Compensación: Densidad.() -> IntOffset)

Si bien estos hacen lo mismo, es decir, establecer el desplazamiento de posición en la vista @Composable, SI usamos compensaciones dinámicas (por ejemplo, compensaciones cambiadas debido a ciertas animaciones o acciones del usuario, etc.) en lugar de compensaciones fijas, siempre debemos usar .offset(Offset: Densidad.() -> IntOffset es decir, la versión lambda. La razón de esto es el último método. evita la recomposición cuando el desplazamiento cambia de valor, lo que mejora considerablemente el rendimiento. Incluso la documentación dice

Este modificador está diseñado para usarse con compensaciones que pueden cambiar debido a la interacción del usuario. Evita la recomposición cuando cambia el desplazamiento y también agrega una capa de gráficos que evita el redibujado innecesario del contexto cuando cambia el desplazamiento.

Si bien no es la implementación más eficiente desde el punto de vista energético, esperamos que esto pueda ser útil como referencia útil para lo mismo. Jetpack Compose y Swift UI son las mejores herramientas para lograr efectos visuales de alta calidad en tan poco tiempo. Creo firmemente que estas dos plataformas permitirán a los desarrolladores móviles crear hermosas experiencias para los usuarios. 🥳

Deja una respuesta

Tu dirección de correo electrónico no será publicada.