Animações e transições do Android

Animação e transição do Android
(1) Animação
O JetpackCompose fornece uma API poderosa e extensível que pode implementar facilmente várias animações na interface do usuário do aplicativo. A seguir, descrevemos como usar essas APIs e quais APIs usar, dependendo da cena da animação.
As animações são cruciais em aplicativos móveis modernos para uma experiência de usuário suave e compreensível. Muitas das APIs do Jetpack Compose Animation estão disponíveis como funções que podem ser compostas, assim como layouts e outros elementos de IU, e são apoiadas por APIs de baixo nível criadas com funções de suspensão de corrotina Kotlin. Este guia começa com uma API de alto nível que é útil em muitos cenários práticos e continua explicando a API de baixo nível que oferece mais controle e personalização.
O diagrama abaixo pode ajudá-lo a decidir qual API usar para animação.
insira a descrição da imagem aqui

(1) Se você deseja animar alterações de conteúdo em seu layout:
Se deseja animar aparência e desaparecimento:
use "Animar Visibilidade".
Trocando conteúdo com base no estado:
Se você estiver fazendo leitura cruzada de conteúdo:
use um crossfade.
Caso contrário, use AnimatedContent.
Caso contrário, use Modifier.animateContentSize.
(2) Se a animação for baseada em estado:
se a animação acontecer durante a composição:
se a animação for infinita:
use RememberInfiniteTransition.
Se estiver animando vários valores ao mesmo tempo:
use updateTransition.
Caso contrário, use animate*AsState.
(3) Se você deseja um controle refinado sobre o tempo de animação:
Use animações como TargetBasedAnimation ou DecayAnimation.
(4) Se a animação é a única fonte de verdade,
use animatable.
(5) Caso contrário, use AnimationState ou animate.

1. API de animação de alto nível
O Compose fornece uma API de animação de alto nível para vários padrões de animação comuns usados ​​em muitos aplicativos. Essas APIs são adaptadas para cumprir as práticas recomendadas do Material Design Motion.

1.1 Visibilidade da Animação
AnimatedVisibility pode combinar a animação de aparecimento e desaparecimento de seu conteúdo.
Exemplo de código:
var editable by Remember { mutableStateOf(true) }
AnimatedVisibility(visible = editable) { Text(text = “Edit”) } Por padrão, o conteúdo aparece gradualmente e expande e desaparece gradualmente e diminui. As transições podem ser personalizadas especificando EnterTransition e ExitTransition. Exemplo de código: var visível por lembre-se { mutableStateOf(true) } val densidade = LocalDensity.current AnimatedVisibility( visible = visible, enter = slideInVertically { // Deslize de 40 dp a partir do topo. with(density) { -40.dp.roundToPx() } } + expandVertical ly( // Expanda a partir do topo. expandFrom = Alignment.Top ) + fadeIn(















// Fade in com o alfa inicial de 0.3f.
initialAlpha = 0.3f
),
exit = slideOutVertically() + shrinkVertically() + fadeOut()
) { Text(“Hello”, Modifier.fillMaxWidth().height(200.dp)) }

1.2 Entrada e saída do Animate para subobjetos
O conteúdo em AnimateVisibility (subobjetos diretos ou indiretos) pode usar o modificador animateEnterExit para especificar diferentes comportamentos de animação para cada subobjeto. O efeito visual de cada criança é uma combinação da animação especificada na composição AnimatedVisibility e as próprias animações de entrada e saída da criança.
AnimatedVisibility(
visible = visible,
enter = fadeIn(),
exit = fadeOut()
) { // Fade in/out do fundo e do primeiro plano. Box(Modifier.fillMaxSize().background(Color.DarkGray)) { Box( Modifier .align(Alignment.Center) .animateEnterExit( // Desliza para dentro/para fora da caixa interna. enter = slideInVertically(), exit = slideOutVertically() ) .sizeIn(minWidth = 256.dp, minHeight = 64.dp) .background(Color.Red) ) { // Conteúdo da notificação…














}
}
}
1.3 Adicionar animação personalizada
Se quiser adicionar efeitos de animação personalizados além das animações de entrada e saída integradas, você precisa acessar a instância básica de Transition por meio da propriedade Transition no lambda de conteúdo de AnimatedVisibility. Quaisquer estados de animação adicionados à instância Transition serão executados simultaneamente com as animações de entrada e saída de AnimatedVisibility. AnimatedVisibility aguardará até que todas as animações na transição sejam concluídas antes de remover seu conteúdo. Para animações de saída criadas independentemente de uma Transition (como usar animate AsState), AnimatedVisibility não será capaz de interpretá-las, portanto, o conteúdo que pode ser composto pode ser removido antes da conclusão AnimatedVisibility( visible = visible , enter
=
fadeIn
(),
exit = fadeOut()
) { // this: AnimatedVisibilityScope
// Use AnimatedVisibilityScope#transition para adicionar uma animação personalizada
// ao
plano de fundo AnimatedVisibility.val por transição.animateColor { state ->
if (state == EnterExitState.Visible) Color.Blue else Color.Gray
}
Box(modifier = Modifier.size(128.dp).background(background))
}
1.4 Animate
AsState
A função animate*AsState é a API de animação mais simples no Compose para animar um único valor. Basta fornecer um valor final (ou valor de destino) e a API começará a animar do valor atual para o valor especificado
val alpha: Float by animateFloatAsState(if (enabled) 1f else 0.5f)
Box(
Modifier.fillMaxSize()
.graphicsLayer(alpha = alpha)
.background(Color.Red)
)
1.5 Animar filhos entra/sai
com AnimatedVis ibility, o modificador animateEnterExit está disponível no Animate lambda de conteúdo de tedContent. Use esta opção para aplicar EnterAnimation e ExitAnimation individualmente a cada objeto filho direto ou indireto
1.6 Adicionando animações personalizadas
Assim como AnimatedVisibility, os campos de transição estão disponíveis no lambda de conteúdo do AnimatedContent. Use esta opção para criar efeitos de animação personalizados que são executados simultaneamente com as transições AnimatedContent.
1.7 Animar o tamanho do conteúdo
O modificador animateContentSize anima as mudanças de tamanho.
var message por Remember { mutableStateOf("Hello") }
Box(
modifier = Modifier.background(Color.Blue).animateContentSize()
) { Text(text = message) } 1.8 Atualizando transições As transições gerenciam uma ou mais animações como seus filhos e as executam simultaneamente em vários estados. O estado pode ser de qualquer tipo de dados. enum class BoxState { Collapsed, Expanded } var currentState por Remember { mutableStateOf(BoxState.Collapsed) } val transição = updateTransition(currentState) val rect por transição.animateRect { state -> when (state) { BoxState.Collapsed -> Rect(0f, 0f, 100f, 100f) BoxState. Expanded -> Rect(100f, 100f , 300f, 300f) } }

















val borderWidth por transição.animateDp { estado ->
quando (estado) { BoxState.Collapsed -> 1.dp BoxState.Expanded -> 0.dp } } enum class DialerState { DialerMinimized, NumberPad }




@Composable
fun DialerButton(isVisibleTransition: Transition) { // dispensa a necessidade do conteúdo saber // sobre outros DialerStates. Em vez disso, o conteúdo pode se concentrar em // animar a mudança de estado entre visível e não visível. }
isVisibleTransition


@Composable
fun NumberPad(isVisibleTransition: Transition) { // dispensa a necessidade do conteúdo saber // sobre outros DialerStates. Em vez disso, o conteúdo pode se concentrar em // animar a mudança de estado entre visível e não visível. }
isVisibleTransition


@Composable fun
Dialer(dialerState: DialerState) { valtransition = updateTransition(dialerState) Box { // Cria transições filhas separadas do tipo booleano para NumberPad // e DialerButton para qualquer animação de conteúdo entre visível e // não visível medido } ) } }
















1.9 Encapsular transições e torná-las reutilizáveis
​​Para casos de uso simples, definir animações de transição no mesmo elemento que pode ser composto da IU é uma opção muito eficaz. No entanto, ao lidar com componentes complexos com vários valores animados, pode ser desejável separar a implementação da animação da IU que pode ser composta.

Isso pode ser feito criando uma classe que contém todos os valores de animação e uma função "atualizar" que retorna uma instância dessa classe. A implementação de conversão pode ser extraída em uma nova função separada. Esse padrão é útil quando você precisa centralizar a lógica de animação ou tornar reutilizáveis ​​animações complexas.
enum class BoxState { Recolhido, Expandido }

@Composable
fun AnimatingBox(boxState: BoxState) { valtransitionData = updateTransitionData(boxState) // Árvore da interface do usuário Box( modifier = Modifier .background(transitionData.color) .size(transitionData.size) ) }







// Mantém os valores da animação.
classe privada TransitionData(
cor: Estado,
tamanho: Estado
) { val cor por cor val tamanho por tamanho }


// Cria uma transição e retorna seus valores de animação.
@Composable
private fun updateTransitionData(boxState: BoxState): TransitionData { valtransition = updateTransition(boxState) val color =transition.animateColor { state -> when (state) { BoxState.Collapsed -> Color.Gray BoxState.Expanded -> Color.Red } } val size = transaction.animateDp { state -> when (state) { BoxState.Collapsed -> 64.dp BoxState. Expandido -> 128.dp } } return Remember(transition) { TransitionData(color, size) } } 2.低级动画API
















As funções animate*AsState são a API mais simples, renderizando alterações instantâneas de valor como valores animados. É apoiado por Animatable, uma API baseada em corrotina para animar um único valor. updateTransition cria um objeto de transição que pode gerenciar vários valores de animação e executá-los com base nas mudanças de estado. RememberInfiniteTransition é semelhante, mas cria uma transição infinita que pode gerenciar várias animações que são executadas indefinidamente. Com exceção do Animatable, todas essas APIs podem ser compostas, o que significa que essas animações podem ser criadas fora da composição.
Todas essas APIs são baseadas na API de animação mais básica. Embora a maioria dos aplicativos não interaja diretamente com o Animation, algumas das funcionalidades personalizadas do Animation estão disponíveis por meio de APIs de nível superior.
insira a descrição da imagem aqui

2.1 Animatable
Animatable é um detentor de valor que pode ser animado quando o valor é alterado via animateTo. Esta é a API que suporta implementações animate*AsState. Ele garante continuidade consistente e exclusividade mútua, ou seja, as alterações de valores são sempre persistentes e quaisquer animações em andamento serão canceladas.
Muitas das funcionalidades do Animatable, incluindo animateTo , são fornecidas como funções de suspensão. Isso significa que eles precisam ser encapsulados no escopo de co-rotina apropriado.
// Começa cinza e anima para verde/vermelho com base em ok
val color = Remember { Animatable(Color.Gray) }
LaunchedEffect(ok) { color.animateTo(if (ok) Color.Green else Color.Red) } Box(Modifier.fillMaxSize().background(color.value)) 2.2 Animação Animação é a API de animação de nível mais baixo disponível. Muitas das animações que vimos até agora são construídas sobre animações. Existem dois subtipos de animação: TargetBasedAnimation e DecayAnimation. As animações só podem ser usadas para controlar manualmente o tempo das animações. A animação é stateless, não tem nenhuma noção de ciclo de vida. Ele atua como um mecanismo de cálculo de animação usado pela API de alto nível. 2.2.1 Animação de referência de destino






Outras APIs cobrem a maioria dos casos de uso, mas com TargetBasedAnimation você pode controlar diretamente o tempo de reprodução da animação. No exemplo abaixo, o tempo de reprodução de TargetAnimation é controlado manualmente de acordo com o tempo de quadro fornecido por FrameNanos
val anim = Remember { TargetBasedAnimation( animationSpec = tween(200), typeConverter = Float.VectorConverter, initialValue = 200f, targetValue = 1000f ) } var playTime por Remember { m utableStateOf(0L) }







LaunchedEffect(anim) { val startTime = withFrameNanos { it }

do {
    playTime = withFrameNanos { it } - startTime
    val animationValue = anim.getValueFromNanos(playTime)
} while (someCustomCondition())

}
2.2.2 Animações personalizadas
Muitas APIs de animação geralmente aceitam parâmetros para personalizar seu comportamento.
Especificações de animação
A maioria das APIs de animação permite que os desenvolvedores personalizem as especificações de animação por meio do parâmetro opcional AnimationSpec.
val alpha: Float by animateFloatAsState(
targetValue = if (enabled) 1f else 0.5f,
// Configure a duração da animação e easing.
animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing)
)
2.2.3 tween Definir valor de
animação por animateFloatAsState( targetValue = 1f, animationSpec = tween( durationMillis = 300, atrasoMillis = 50,




2.2.4 Quadros-chave
Os quadros-chave são animados com base em valores instantâneos especificados em diferentes timestamps durante a duração da animação. A qualquer momento, o valor da animação será interpolado entre os dois valores de quadro-chave. Para cada um desses quadros-chave, especifique o Easing para determinar a curva de interpolação.
Opcionalmente, especifique um valor de 0 milissegundos e uma duração. Se esses valores não forem especificados, eles serão padronizados para os valores iniciais e finais da animação, respectivamente,
valor val por animateFloatAsState(
targetValue = 1f,
animationSpec = keyframes { durationMillis = 375 0,0f em 0 com LinearOutSlowInEasing // para 0-15 ms 0,2f em 15 com FastOutLinearInEasing // para 15- 75 ms 0,4 f em 75 // ms 0,4f em 225 // ms } )






2.2.5 infinitoRepetível
infinitoRepetível é como repetível, mas repete um número infinito de iterações.
valor val por animateFloatAsState(
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis = 300),
repeatMode = RepeatMode.Reverse
)
)
(2) Animação de transição (Transition)

Adicionar efeitos de animação para alterações de layout provavelmente requer os seguintes processos:
(1) Crie um objeto Scene (cena) para o layout inicial e o layout final. No entanto, na maioria dos casos, não precisamos criar o objeto Cena do layout inicial, porque a cena do layout inicial geralmente é determinada automaticamente de acordo com o layout atual.
(2) Crie um objeto Transition para definir o tipo de animação desejado.
(3) Chame TransitionManager.go(), o sistema executará a animação para trocar o layout.
Parte da reimpressão vem de: https://blog.csdn.net/xujian197/article/details/117290583
1.1 Criar uma cena
Podemos criar uma instância de cena diretamente do arquivo de layout. Chamar Scene.getSceneForLayout(). Este método aceita três parâmetros, o primeiro parâmetro é o ViewGroup onde a cena está localizada, o segundo parâmetro é o ID do arquivo de layout da cena e o terceiro parâmetro é um objeto Context.
2.1.1

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:
layout_height="match_parent">
<androidx.app compat.widget.Toolbar
android:id="@+id/tool ​​bar"
… >
</androidx.appcompat.widget.Toolbar>


</androidx.constraintlayout.widget.ConstraintLayout>
2.1.2 O primeiro arquivo de layout de cena é o seguinte:

<TextView
android:id="@+id/text_view"
.../>
<ImageView
android:id="@+id/image_view"
.../>

2.1.3 O segundo arquivo de layout de cena é o seguinte:

<ImageView
android:id=“@+id/image_view”
…/>
<TextView
android:id=“@+id/text_view”
…/>

2.1.4 O layout das duas cenas apenas troca as posições das duas Views (com o mesmo ID). O código a seguir mostra como criar um objeto Scene a partir do arquivo de layout: val sceneRoot: ViewGroup = findViewById(R.id.scene_root) val aScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, mContext) val bScene: Scene = Scene.getSceneForLayout(s ceneRoot, R.layout.b_scene, mContext) 2.1.5 Criar tipo de animação de transição O tipo de animação de transição pode ser especificado no arquivo de recurso ou
diretamente
no
código . Se precisar especificar o tipo de animação de transição no arquivo de recurso, você pode adicioná-lo no diretório res/transition/. O arquivo abaixo especifica uma transição Fade. res/transition/fade_transition.xml 2.1.6 Use TransitionInflater no código para carregar a animação de transição. ValfadeTransition=TransitionInflater.from(mContext).inflateTransition(R.transition.fade_transition) 2.2 Inicie a transição 2.2.1 Chame TransitionManager.go() para iniciar a animação da transição. Este método aceita dois parâmetros, o primeiro parâmetro é o objeto de cena final do layout (cena final) e o segundo é a instância do tipo de animação de transição (transição). Você também não pode especificar o tipo de animação de transição. A estrutura usará transições padrão para animar entre as cenas. Por padrão, as cenas de saída executam uma animação de saída e as cenas de entrada executam uma animação de entrada.








2.2.2 Mas, às vezes, podemos precisar fazer algumas operações extras ao entrar ou sair da cena. Por exemplo, adicionar efeitos de animação a exibições que não estão na mesma hierarquia. Neste momento, você pode criar um objeto Runnable e passá-lo para o método Scene.setExitAction() ou Scene.setEnterAction(). A estrutura chama o método setExitAction() na cena inicial antes de executar a animação de transição e chama o método setEnterAction() na cena final após executar a animação de transição.
Transição sem cenas
2.2.3 Alterar a hierarquia de visualização não é a única forma de modificar a interface, você também pode modificar as subvisualizações na hierarquia de visualização atual. Se você deseja modificar a interface para aplicar transições em uma única hierarquia de exibição, pode usar TransitionManager.beginDelayedTransition() para criar uma transição atrasada. A estrutura de animação de transição anima a transição entre o estado original e o novo estado quando as subvisualizações na interface mudam.
Use a animação de transição para adicionar efeitos de animação à alternância da Activity
2.2.4 Before Android 5.0, se precisarmos alterar a animação de alternância de Activity padrão. Pode ser necessário adicionar um método overridePendingTransition() após startActivity() e finish(). Este método aceita dois parâmetros, o primeiro parâmetro é entrar na animação e o segundo parâmetro é sair da animação. Por exemplo, Atividade A abre uma Atividade B. O primeiro parâmetro é a animação de entrada de B e o segundo parâmetro é a animação de saída de A. Pressione a tecla Enter para fechar a Atividade B, o primeiro parâmetro é a animação de entrada de A e o segundo parâmetro é a animação de saída de B.
Ou defina-os separadamente no arquivo de estilo do tema.

2.2.5 A animação de transição traz uma nova animação de transição de atividade, essas animações de transição podem ser direcionadas para a exibição dentro da atividade. Podem ser transições de entrada e saída, bem como elementos compartilhados entre Activities.
1. A transição de entrada determina como a exibição na Atividade entra na cena
2. A transição de saída determina como a exibição na Atividade sai da cena
3. A transição do elemento compartilhado determina como a exibição compartilhada por duas Atividades transita entre essas Atividades.

O Android oferece suporte às três transições de entrada e saída a seguir.
1. Explodir, mova a visão para dentro ou fora do centro da cena.
2. Deslize para mover a exibição para dentro ou para fora de uma das bordas da cena.
3. Fade, alterando a opacidade da visualização, adicione ou remova a visualização na cena.

2.2.6 O Android também suporta as seguintes transições de elementos compartilhados.
1. ChangeBounds adiciona efeitos de animação às alterações nos limites do layout da visualização de destino.
2.ChangeClipBounds adiciona efeitos de animação a alterações no limite de recorte da visualização de destino
3.ChangeTransform adiciona efeitos de animação a alterações no zoom e rotação da visualização de destino
4.ChangeImageTransform adiciona efeitos de animação a alterações no tamanho e zoom da imagem de destino

2.2.7 Use o código para especificar a transição para a troca da Atividade
. Window.setEnterTransition() especifica a transição de entrada para abrir a Atividade.
Window.setExitTransition() especifica a transição de saída que abre uma Atividade
e faz com que a Atividade saia do primeiro plano.
Transição de saída da cidade

Em circunstâncias normais, precisamos apenas definir EnterTransition e ExitTransition. ReenterTransition usará a versão reversa de ExitTransition e ReturnTransition usará a versão reversa de EnterTransition. O código a seguir especifica uma transição de entrada para a Activity que desliza da borda direita
fun setupWindowAnimations() { val slideTransition = Slide().apply { slideEdge = Gravity.END duration = 300L } window.enterTransition = slideTransition } 2.2.8 Ou podemos especificar a transição da Activity no arquivo de estilo do tema






2.2.9 Finalmente, fazer a animação de transição funcionar. A Activity deve ser iniciada com startActivity(Intent intent, Bundle options) e finishAfterTransition() deve ser chamado quando a Activity for fechada. O objeto Bundle pode ser obtido pelo método ActivityOptionsCompat.makeSceneTransitionAnimation(Activity activity).
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(this)
startActivity(intent, options)
2.3 Transições de elemento compartilhado
Iniciar uma animação de transição de elemento compartilhado é simples.
1. Primeiro, adicione um atributotransitionName à exibição compartilhada da atividade de destino.
2. Use o método ActivityOptionsCompat.makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName) para obter um objeto Bundle. O parâmetro sharedElement representa a exibição para fazer a transição para a atividade de destino. sharedElementName representa o valor do atributo de transiçãoName da exibição compartilhada na atividade de destino.
3. Use startActivity(intenção, opções de pacote) para iniciar a atividade de destino.
3. Gerenciador de Transição
Esta classe gerencia um conjunto de transições que disparam quando a cena muda. Para usar o gerenciador, adicione uma cena e um objeto de transição que chame setTransition(android.transition.Scene, android.ttransition.transition) ou setTransition(android.transition.Sene, android.Ttransition.Scene., android.teransition.Transaction). Não há necessidade de definir transições específicas para mudanças de cena; por padrão, as mudanças de cena usarão "autotransição" para fazer algo razoável para a maioria das situações. Transições adicionais precisam ser especificadas para alterações de cena específicas somente se o aplicativo exigir um comportamento de transição diferente nesses casos.

TransitionManagers podem ser declarados em arquivos de recursos XML no diretório res/transition. O recurso TransitionManager consiste no nome da tag TransitionManager e contém uma ou mais tags de transição, cada tag de transição descreve a relação entre a transição e as informações de/para a cena na tag. Por exemplo, aqui está um arquivo de recurso que declara várias transições de cena:

Para cada uma das propriedades fromScene e toScene, há uma referência a um arquivo de layout XML padrão. Isso é equivalente a criar uma cena a partir de um layout no código chamando scene#getSceneForLayout(ViewGroup, int, Context). Para a propriedade de transição, há uma referência a um arquivo de recurso no diretório res/transition que descreve a transição.
3.1 Resumo
insira a descrição da imagem aqui
insira a descrição da imagem aqui

3.2Métodos públicos
beginDelayedTransition
open static fun beginDelayedTransition(sceneRoot: ViewGroup!):
Método conveniente da unidade para animar uma nova cena definida por todas as alterações na raiz da cena fornecida entre a chamada deste método e o próximo quadro renderizado usando a transição padrão. Equivalente a chamar beginDelayedTransition (android.view.ViewGroup, android.transition.transition), o valor do parâmetro de transição é nulo.
insira a descrição da imagem aqui

3.3beginDelayedTransition
open static fun beginDelayedTransition(
cenaRoot: ViewGroup!,
transition: Transition!
):Unidade
insira a descrição da imagem aqui

Wang Kaige 116052020083 http://t.csdn.cn/aaMeD

Acho que você gosta

Origin blog.csdn.net/fjnu_se/article/details/128209765
Recomendado
Clasificación