Puedes animar tus tarjetas de varias maneras, como las siguientes:
- Transiciones de barrido con animaciones de interpolación
- Atenuación y deslizamiento suave de animaciones dentro y fuera de una tarjeta
Cómo mostrar una transición de barrido
Para mostrar un barrido suave de un valor a otro, puedes habilitar las animaciones de interpolación de un elemento, como se muestra en el siguiente fragmento de código:
private var startValue = 15f private var endValue = 105f private val animationDurationInMillis = 2000L // 2 seconds override fun onTileRequest(requestParams: RequestBuilders.TileRequest): ListenableFuture<Tile> { val circularProgressIndicator = CircularProgressIndicator.Builder() .setProgress( FloatProp.Builder(/* static value */ 0.25f) .setDynamicValue( // Or you can use some other dynamic object, for example // from the platform and then at the end of expression // add animate(). DynamicFloat.animate( startValue, endValue, AnimationSpec.Builder() .setAnimationParameters( AnimationParameters.Builder() .setDurationMillis(animationDurationInMillis) .build() ) .build(), ) ) .build() ) .build() return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement(circularProgressIndicator)) .build() ) }
Cómo establecer la dirección del arco
Si tu tarjeta contiene un arco, es posible que no quieras que la línea del arco o el texto siempre crezcan en la dirección de texto predeterminada del idioma que eligió el usuario. Para especificar una dirección de crecimiento de arco, usa las APIs de ArcDirection
:
public override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile> { return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( EdgeContentLayout.Builder(deviceParameters) .setResponsiveContentInsetEnabled(true) .setEdgeContent( Arc.Builder() // Arc should always grow clockwise. .setArcDirection(LayoutElementBuilders.ARC_DIRECTION_CLOCKWISE) .addContent( ArcLine.Builder() // Set color, length, thickness, and more. // Arc should always grow clockwise. .setArcDirection( LayoutElementBuilders.ARC_DIRECTION_CLOCKWISE ) .build() ) .build() ) .build() ) ) .build() ) }
Cómo mostrar una atenuación o deslizamiento suave
Para indicar con mayor claridad que un elemento aparece o desaparece en una tarjeta, o para mostrar de forma más sutil un cambio de paso en el valor de una tarjeta, usa efectos de atenuación y deslizamiento en tus animaciones de tarjetas.
Si un diseño de tarjeta contiene un elemento cuyo valor cambia, la tarjeta muestra la animación de salida del elemento y, luego, actualiza el diseño y muestra la animación de entrada del elemento.
Transiciones de atenuación
En el siguiente fragmento de código, se muestra cómo realizar transiciones de fundido de entrada y de salida con los métodos auxiliares de DefaultContentTransitions
. Para definir objetos FadeInTransition
y FadeOutTransition
personalizados, llama a setFadeIn()
y setFadeOut()
, respectivamente, en la transición de los métodos set.
public override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile> { // Assumes that you've defined a custom helper method called // getTileTextToShow(). val tileText = getTileTextToShow() return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, tileText) .setModifiers( Modifiers.Builder() .setContentUpdateAnimation( AnimatedVisibility.Builder() .setEnterTransition(DefaultContentTransitions.fadeIn()) .setExitTransition(DefaultContentTransitions.fadeOut()) .build() ) .build() ) .build() ) ) .build() ) }
Transiciones de deslizamiento
En este otro fragmento de código, se muestra cómo realizar transiciones de deslizamiento hacia adentro y afuera con los métodos auxiliares de DefaultContentTransitions
. También puedes definir objetos SlideInTransition
y SlideOutTransition
personalizados llamando a setSlideIn()
y setSlideOut()
, respectivamente, en los métodos set de transición.
public override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile> { // Assumes that you've defined a custom helper method called // getTileTextToShow(). val tileText = getTileTextToShow() return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, tileText) .setModifiers( Modifiers.Builder() .setContentUpdateAnimation( AnimatedVisibility.Builder() .setEnterTransition( DefaultContentTransitions.slideIn( ModifiersBuilders.SLIDE_DIRECTION_LEFT_TO_RIGHT ) ) .setExitTransition( DefaultContentTransitions.slideOut( ModifiersBuilders.SLIDE_DIRECTION_LEFT_TO_RIGHT ) ) .build() ) .build() ) .build() ) ) .build() ) }
Cómo mostrar una transformación
Para llamar la atención a un elemento o área específicos en una tarjeta, puedes aplicarle varios tipos de transformaciones, como rotación, escalamiento y traslación.
Muchos valores de punto flotante asociados con transformaciones aceptan expresiones dinámicas, que te permiten animar estas transformaciones.
Rotación
Para realizar una rotación en el sentido de las manecillas del reloj alrededor de un punto de pivote personalizable, usa un código similar al siguiente:
return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, someTileText) .setModifiers( Modifiers.Builder() .setTransformation( ModifiersBuilders.Transformation.Builder() // Set the pivot point 50 dp from the left edge // and 100 dp from the top edge of the screen. .setPivotX(dp(50f)) .setPivotY(dp(100f)) // Rotate the element 45 degrees clockwise. .setRotation(degrees(45f)) .build() ) .build() ) .build() ) ) .build() )
Escalado
Para aumentar o reducir un elemento según los factores de escala horizontal y vertical, usa un código similar al siguiente:
return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, someTileText) .setModifiers( Modifiers.Builder() .setTransformation( ModifiersBuilders.Transformation.Builder() // Set the pivot point 50 dp from the left edge // and 100 dp from the top edge of the screen. .setPivotX(dp(50f)) .setPivotY(dp(100f)) // Shrink the element by a scale factor // of 0.5 horizontally and 0.75 vertically. .setScaleX(FloatProp.Builder(0.5f).build()) .setScaleY( FloatProp.Builder(0.75f).build() ) .build() ) .build() ) .build() ) ) .build() )
Traducción geométrica
Para mover un elemento por una cantidad específica de píxeles de densidad (dp) en la pantalla horizontal o verticalmente, usa un código similar al siguiente:
return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, someTileText) .setModifiers( Modifiers.Builder() .setTransformation( ModifiersBuilders.Transformation.Builder() // Translate (move) the element 60 dp to the right // and 80 dp down. .setTranslationX(dp(60f)) .setTranslationY(dp(80f)) .build() ) .build() ) .build() ) ) .build() )
No muestres información importante en medio de una animación
Hay varias situaciones en las que se inhabilitan las animaciones:
- La renderización de tarjetas del sistema puede inhabilitar las animaciones para todas las tarjetas.
- Una tarjeta puede animar solo 4 elementos a la vez. Si intentas animar más de 4 elementos al mismo tiempo, no todos mostrarán una animación.
Cuando se inhabilita una animación, los elementos son estáticos y muestran el valor final de la animación. Por este motivo, no confíes en el comportamiento de la animación, como su duración, para mostrar información importante.