Spostare una visualizzazione con animazione

Gli oggetti sullo schermo spesso devono essere riposizionati a causa dell'interazione dell'utente o dell'elaborazione dietro le quinte. Invece di aggiornare immediatamente la posizione dell'oggetto, che fa lampeggiare da un'area all'altra, utilizza un'animazione per spostarlo dalla posizione iniziale a quella finale.

Un modo in cui Android consente di riposizionare gli oggetti visualizzati sullo schermo consiste nell'utilizzare ObjectAnimator. Specifica la posizione finale in cui vuoi posizionare l'oggetto e la durata dell'animazione. Puoi anche utilizzare interpolatori temporali per controllare l'accelerazione o la decelerazione dell'animazione.

Modifica della posizione della visualizzazione con ObjectAnimator

L'API ObjectAnimator consente di modificare le proprietà di una vista con una durata specificata. Contiene metodi statici per creare istanze di ObjectAnimator a seconda del tipo di attributo che stai animando. Quando riposiziona le viste sullo schermo, utilizza gli attributi translationX e translationY.

Ecco un esempio di ObjectAnimator che sposta la visualizzazione in una posizione di 100 pixel dal lato sinistro dello schermo in 2 secondi:

Kotlin

ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    duration = 2000
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f);
animation.setDuration(2000);
animation.start();

In questo esempio viene utilizzato il metodo ObjectAnimator.ofFloat(), perché i valori di traslazione devono essere in virgola mobile. Il primo parametro è la visualizzazione che vuoi animare. Il secondo parametro è la proprietà che stai creando. Poiché la vista deve essere spostata orizzontalmente, viene utilizzata la proprietà translationX. L'ultimo parametro è il valore finale dell'animazione. In questo esempio, il valore 100 indica la posizione di un determinato numero di pixel dalla sinistra dello schermo.

Il metodo Next specifica la durata dell'animazione in millisecondi. In questo esempio, l'animazione viene eseguita per 2 secondi (2000 millisecondi).

L'ultimo metodo attiva l'animazione, che aggiorna la posizione della visualizzazione sullo schermo.

Per ulteriori informazioni sull'uso di ObjectAnimator, consulta Creazione di animazioni mediante ObjectAnimator.

Aggiungi movimento curvo

Sebbene l'utilizzo di ObjectAnimator sia pratico, per impostazione predefinita riposiziona la vista lungo una linea retta tra il punto iniziale e quello finale. Il material design si basa sulle curve per il movimento spaziale degli oggetti sullo schermo e la tempistica di un'animazione. Il movimento curvo conferisce all'app un aspetto più matematico e rende le animazioni più interessanti.

Definisci il tuo percorso

La classe ObjectAnimator dispone di costruttori che consentono di animare le coordinate utilizzando due o più proprietà contemporaneamente insieme a un percorso. Ad esempio, il seguente animatore utilizza un oggetto Path per animare le proprietà X e Y di una vista:

Kotlin

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    val path = Path().apply {
        arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true)
    }
    val animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path).apply {
        duration = 2000
        start()
    }
} else {
    // Create animator without using curved path
}

Java

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  Path path = new Path();
  path.arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true);
  ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
  animator.setDuration(2000);
  animator.start();
} else {
  // Create animator without using curved path
}

Ecco l'aspetto dell'animazione arco:

Figura 1. Un'animazione con percorso curvo.

Un elemento Interpolator è un'implementazione di una curva di interpolazione. Consulta la documentazione di Material Design per ulteriori informazioni sul concetto di curve di interpolazione. Un elemento Interpolator definisce il modo in cui i valori specifici di un'animazione vengono calcolati in funzione del tempo. Il sistema fornisce risorse XML per le tre curve di base della specifica di Material Design:

  • @interpolator/fast_out_linear_in.xml
  • @interpolator/fast_out_slow_in.xml
  • @interpolator/linear_out_slow_in.xml

Utilizzo di PathInterpolator

La classe PathInterpolator è un interpolatore introdotto in Android 5.0 (API 21). Si basa su una curva di Bézier o un oggetto Path. Gli esempi per Android nella documentazione di Material Design per l'easing utilizzano PathInterpolator.

PathInterpolator ha costruttori basati su diversi tipi di curve di Bézier. Tutte le curve di Bézier hanno punti di inizio e fine fissi rispettivamente a (0,0) e (1,1). Gli altri argomenti del costruttore dipendono dal tipo di curva di Bézier creata.

Ad esempio, per una curva di Bézier quadratica sono necessarie solo le coordinate X e Y di un punto di controllo:

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PathInterpolator(0.67f, 0.33f)
} else {
    LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  myInterpolator = new PathInterpolator(0.67f, 0.33f);
} else {
  myInterpolator = new LinearInterpolator();
}

In questo modo si produce una curva di interpolazione che inizia rapidamente e rallenta con l'avvicinarsi alla fine.

Allo stesso modo, il costruttore di Bézier cubico ha punti di inizio e fine fissi, ma richiede due punti di controllo:

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f)
} else {
    LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  myInterpolator = new PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f);
} else {
  myInterpolator = new LinearInterpolator();
}

Questa è un'implementazione della curva di easing di Material Design enfatizzata di decelerazione.

Per un maggiore controllo, è possibile utilizzare un valore Path arbitrario per definire la curva:

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  val path = Path().apply {
    moveTo(0.0f, 0.0f)
    cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f)
  }
  PathInterpolator(path)
} else {
  LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  Path path = new Path();
  path.moveTo(0.0f, 0.0f);
  path.cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f);
  myInterpolator = new PathInterpolator(path);
} else {
  myInterpolator = new LinearInterpolator();
}

Questo produce la stessa curva di interpolazione dell'esempio cubico di Bézier, ma utilizza invece un Path.

Puoi anche definire un interpolatore dei percorsi come risorsa XML:

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.5"
    android:controlY1="0.7"
    android:controlX2="0.1f"
    android:controlY2="1.0f"/>

Dopo aver creato un oggetto PathInterpolator, puoi passarlo al metodo Animator.setInterpolator(). Animator utilizza l'interpolatore per determinare la curva di temporizzazione o del percorso all'avvio.

Kotlin

val animation = ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    interpolator = myInterpolator
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f);
animation.setInterpolator(myInterpolator);
animation.start();