É possível animar os blocos de algumas maneiras diferentes, incluindo:
- Transições de varredura usando animações de interpolação.
- Animações de esmaecimento e deslize suaves para dentro e para fora de um bloco.
Mostrar uma transição de varredura
Para mostrar uma transição Limpar suave de um valor para outro, ative as animações de interpolação de um elemento, conforme mostrado no snippet de código abaixo:
Kotlin
private val defaultValue = 0f private var startValue = 15f private var endValue = 105f private val animationDurationInMillis = 2000f // 2 seconds override fun onTileRequest(requestParams: TileRequest) = Futures.immediateFuture( // Add timeline and layout containers. CircularProgressIndicator is an // inner element of those containers. 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() // Finish building all elements that contain CircularProgressIndicator. )
Java
private float defaultValue = 0f; private float startValue = 15f; private float endValue = 105f; private float animationDurationInMillis = 2000f; // 2 seconds @Override protected ListenableFuture<Tile> onTileRequest( @NonNull TileRequest requestParams ) { return Futures.immediateFuture( // Add timeline and layout containers. CircularProgressIndicator is an // inner element of those containers. new CircularProgressIndicator.Builder() .setProgress( new 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, new AnimationSpec.Builder() .setAnimationParameters( new AnimationParameters.Builder() .setDurationMillis(animationDurationInMillis) .build() ).build() ) ).build() ).build() // Finish building all elements that contain CircularProgressIndicator. ); }
Definir direção do arco
Se o bloco tiver um arco, talvez você não queira que a linha do arco ou o texto sempre
aumentar a direção de texto padrão para o idioma escolhido pelo usuário. Para especificar
uma direção de crescimento do arco, use as APIs ArcDirection
:
Kotlin
@OptIn(ProtoLayoutExperimental::class) public override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile> { return Futures.immediateFuture(Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement( EdgeContentLayout.Builder(deviceParameters) .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() ) }
Java
@OptIn(markerClass = ProtoLayoutExperimental.class) @NonNull @Override protected ListenableFuture<Tile> onTileRequest( @NonNull RequestBuilders.TileRequest requestParams ) { return Futures.immediateFuture(new Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement( new EdgeContentLayout.Builder(deviceParameters) .setEdgeContent( new Arc.Builder() // Arc should always grow clockwise. .setArcDirection(LayoutElementBuilders.ARC_DIRECTION_CLOCKWISE) .addContent( new ArcLine.Builder() // Set color, length, thickness, and more. // Arc should always grow clockwise. .setArcDirection( LayoutElementBuilders.ARC_DIRECTION_CLOCKWISE) .build()) .build()) .build())) .build() ); }
Mostrar um deslize ou esmaecimento suave
Para indicar mais claramente que um elemento está aparecendo ou desaparecendo em um bloco ou para mostrar de forma mais sutil uma mudança de etapa no valor de um bloco, use os efeitos de esmaecer e deslizar nas animações de blocos.
Se um layout de blocos tiver um elemento que muda de valor, o bloco vai mostrar a animação de saída do elemento, atualizar o layout e mostrar a animação de entrada do elemento.
Transições Esmaecer
O snippet de código abaixo demonstra como realizar transições de esmaecimento e exibição gradual usando os métodos auxiliares de DefaultContentTransitions
. Para
definir objetos FadeInTransition
e FadeOutTransition
personalizados, chame
setFadeIn()
e setFadeOut()
, respectivamente, nos métodos
setter da transição.
Kotlin
@OptIn(ProtoLayoutExperimental::class) 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( ModifiersBuilders.Modifiers.Builder() .setContentUpdateAnimation(AnimatedVisibility.Builder() .setEnterTransition( DefaultContentTransitions.fadeIn()) .setExitTransition( DefaultContentTransitions.fadeOut() ).build()) ).build()) ).build() ) }
Java
@OptIn(markerClass = ProtoLayoutExperimental.class) @NonNull @Override protected ListenableFuture<Tile> onTileRequest( @NonNull RequestBuilders.TileRequest requestParams ) { // Assumes that you've defined a custom helper method called // getTileTextToShow(). String tileText = getTileTextToShow(); return Futures.immediateFuture(new Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement( new Text.Builder(this, tileText) .setModifiers( new ModifiersBuilders.Modifiers.Builder() .setContentUpdateAnimation(new AnimatedVisibility.Builder() .setEnterTransition( DefaultContentTransitions.fadeIn()) .setExitTransition( DefaultContentTransitions.fadeOut()) .build()) .build())) .build() ); }
Transições de deslize
Este outro snippet de código demonstra como realizar transições de deslize de entrada e saída usando
os métodos auxiliares de DefaultContentTransitions
(link em inglês). Também
é possível definir objetos SlideInTransition
e SlideOutTransition
personalizados
chamando setSlideIn()
e setSlideOut()
, respectivamente, nos métodos
setter da transição.
Kotlin
@OptIn(ProtoLayoutExperimental::class) 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( SLIDE_DIRECTION_LEFT_TO_RIGHT) ).setExitTransition( DefaultContentTransitions.slideOut( SLIDE_DIRECTION_LEFT_TO_RIGHT) ).build() ).build() ).build() )).build() ) }
Java
@OptIn(markerClass = ProtoLayoutExperimental.class) @NonNull @Override protected ListenableFuture<Tile> onTileRequest( @NonNull RequestBuilders.TileRequest requestParams ) { // Assumes that you've defined a custom helper method called // getTileTextToShow(). String tileText = getTileTextToShow(); return Futures.immediateFuture(Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement( new Text.Builder(this, tileText) .setModifiers( new Modifiers.Builder() .setContentUpdateAnimation( new AnimatedVisibility.Builder() .setEnterTransition( DefaultContentTransitions.slideIn( SLIDE_DIRECTION_LEFT_TO_RIGHT)) .setExitTransition( DefaultContentTransitions.slideOut( SLIDE_DIRECTION_LEFT_TO_RIGHT)) .build()) .build()) .build())) .build() ); }
Mostrar uma transformação
Para chamar a atenção para um elemento ou área específica em um bloco, é possível aplicar diversas tipos de transformações nele, incluindo: rotação, escalonamento e translação.
Muitos valores de ponto flutuante associados a transformações aceitam expressões dinâmicas, que permitem animar essas transformações.
Rotação
Para fazer uma rotação no sentido horário sobre um pivô personalizável, use o código semelhante a:
Kotlin
// Last line in your onTileRequest() method implementation. return Futures.immediateFuture(Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement( Text.Builder(this, someTileText) .setModifiers( 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(50)) .setPivotY(dp(100)) // Rotate the element 45 degrees clockwise. .setRotation( degrees(45f) ).build() ).build()) ).build() )
Java
// Last line in your onTileRequest() method implementation. return Futres.immediateFuture(new Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement( new Text.Builder(this, someTileText) .setModifiers( new 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(50)) .setPivotY(dp(100)) // Rotate the element 45 degrees clockwise. .setRotation( degrees(45f)) .build()) .build())) .build() );
Dimensionamento
Para aumentar ou diminuir um elemento com base em fatores de escalonamento horizontal e vertical, use semelhante a este:
Kotlin
// Last line in your onTileRequest() method implementation. return Futures.immediateFuture(Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement( Text.Builder(this, someTileText) .setModifiers( 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(50)) .setPivotY(dp(100)) // Shrink the element by a scale factor // of 0.5 horizontally and 0.75 vertically. .setScaleX(TypeBuilders.FloatProp.Builder(0.5f) .build()) .setScaleY(TypeBuilders.FloatProp.Builder(0.75f) .build() ).build() ).build()) ).build() )
Java
// Last line in your onTileRequest() method implementation. return Futres.immediateFuture(new Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement( new Text.Builder(this, someTileText) .setModifiers( new 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(50)) .setPivotY(dp(100)) // Shrink the element by a scale factor // of 0.5 horizontally and 0.75 vertically. .setScaleX(new TypeBuilders.FloatProp.Builder(0.5f) .build()) .setScaleY(new TypeBuilders.FloatProp.Builder(0.75f) .build()) .build()) .build())) .build() );
Translação geométrica
Mover um elemento por um número específico de pixels de densidade (dp) pela tela horizontal ou verticalmente, use um código semelhante a este:
Kotlin
// Last line in your onTileRequest() method implementation. return Futures.immediateFuture(Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement( Text.Builder(this, someTileText) .setModifiers( ModifiersBuilders.Transformation.Builder() // Translate (move) the element 60 dp to the right // and 80 dp down. .setTranslationX(dp(60)) .setTranslationY(dp(80)) .build() ).build()) ).build() )
Java
// Last line in your onTileRequest() method implementation. return Futres.immediateFuture(new Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement( new Text.Builder(this, someTileText) .setModifiers( new ModifiersBuilders.Transformation.Builder() // Translate (move) the element 60 dp to the right // and 80 dp down. .setTranslationX(dp(60)) .setTranslationY(dp(80)) .build()) .build())) .build() );
Não mostrar informações importantes durante uma animação
Há várias situações em que as animações são desativadas:
- A renderização de blocos do sistema pode desativar as animações de todos os blocos.
- Um bloco pode animar apenas quatro elementos por vez. Se você tentar animar mais do que isso ao mesmo tempo, nem todos os elementos terão animações.
Quando uma animação é desativada, os elementos ficam estáticos e mostram o valor final da animação. Por esse motivo, não dependa do comportamento da animação, como a duração dela, para mostrar informações importantes.