Marquesina con Jetpack Compose. Mira cómo hacer un… | de Victor Brandalise | noviembre 2022
Hace unas semanas, estaba construyendo un rastreador de presupuesto usando Compose y necesitaba un texto de marquesina, o en otras palabras, un componente que desplazara el texto si el texto no encajaba dentro de sus límites. Jetpack Compose no ofrece nada como esto Después de algunas investigaciones encontré este componente.Funciona en la mayoría de los casos, pero el código no es tan fácil de entender. Hoy vamos a revisar el código para entender cómo funciona e intentar mejorarlo.Si el texto se ajusta a sus límites, MarqueeText funciona como un componente de texto normal; de lo contrario, se crea otro componente de texto para crear ese efecto de desplazamiento genial. Podemos ver que el componente MarqueeText tiene muchos campos, casi los mismos campos que tiene un componente de texto normal, porque la marquesina básicamente los envuelve. La única diferencia es gradientEdgeColor, que define el color en los bordes del componente. El lambda createText se usa para crear el componente de texto, se define como un lambda porque se pueden crear varias instancias del componente de texto. A continuación, la variable de desplazamiento representa el desplazamiento x del primer componente de texto, textLayoutInfoState se usa para almacenar información sobre el texto y el ancho del contenedor. En la siguiente parte tenemos el código que realiza la animación logrando un comportamiento similar pero entendamos por qué con FrameNanos en particular. Según su documentación:
Hace una pausa hasta que se solicita un nuevo marcollama inmediatamente a onFrame con el tiempo de fotograma en nanosegundos en el contexto de llamada de despacho de fotogramas y luego continúa con el resultado del fotograma onFrame, no necesariamente un valor directo de «ahora».
Como puede ver, esta función se suspende hasta que se solicite un nuevo cuadro, lo que significa que tiene la oportunidad de actualizar su animación antes de que se dibuje un nuevo cuadro. Si tiene una pantalla de 60 fps, eso significa que la pantalla se actualiza 60 veces por segundo. Si actualiza su animación 80 veces por segundo, está desperdiciando recursos porque algunas actualizaciones nunca se dibujan. Lo mismo ocurre si dibuja 15 veces por segundo, el usuario notará una animación entrecortada. withFrameNanos resuelve este problema haciendo una pausa hasta que se solicite un nuevo cuadro, por lo que no tiene que preocuparse por la velocidad de cuadros de la pantalla. La siguiente parte del código usa un SubcomposeLayout para diseñar los componentes. Primero, comienza a subcomponer el componente de texto principal y lo mide como si no hubiera restricciones de ancho. Necesitamos hacer esto para saber si el texto se ajusta a las restricciones o no. Luego se definen las variables para el degradado y el segundo componente de texto, se pueden anular porque es posible que no se necesiten si el texto se ajusta a sus restricciones. Si el texto se ajusta a sus restricciones, mainText se actualiza para llenar el ancho máximo. Además, textLayoutInfoState se establece en nulo para que la animación no se ejecute. Si el texto no se ajusta a sus restricciones, se definen los componentes de degradado y segundo texto. Finalmente, se ordenan los componentes. Inicialmente el componente marquesina parece complejo, pero con el análisis se va analizando un poco, poco a poco vemos que no es tan complejo. Durante este análisis encontré algunas cosas que se podrían mejorar en el código. Solo mencionaré algunos de los cambios que hice, si quieres verlos todos, hay un enlace al código fuente al final del artículo. Dentro del bloque LaunchedEffect hay dos bucles while que parecen sospechosos, el primero es while (verdadero), se puede eliminar sin afectar nada. El segundo es while (!animation.isFinishedFromNanos(playTime)) ya que sabemos que la animación nunca termina, así que lo cambié a while (isActive), esto devuelve verdadero mientras la rutina está activa. También eliminé el retraso, no creo que sea necesario para una marquesina. También podemos modificar el componente MarqueeText para seguir el patrón de ranura. Creé un nuevo componente llamado Marquee y cambié su firma para aceptar cualquier tipo de contenido. De esta manera, puede darle a la marquesina el contenido que desee, incluso si no es texto. Esta es la línea de fondo