J'ai eu l'opportunité de mettre en place une animation "ressembler à flottant" sur Android. Cela ressemble à l'image suivante.
Cette animation
Est réalisé en exécutant "en continu" et "à plusieurs reprises". «En continu» signifie que lorsque l'animation de 1. est terminée, l'animation de 2. est lancée.
Faire cela avec l'API d'animation View d'Android est généralement un code terrible. Ensuite, c'est ça.
//Animation qui monte en 2 secondes
final TranslateAnimation anim1 = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, -0.1f);
anim1.setDuration(2000);
//Animation qui descend en 2 secondes
final TranslateAnimation anim2 = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, -0.1f,
Animation.RELATIVE_TO_SELF, 0.0f);
anim2.setDuration(2000);
anim1.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) { }
@Override
public void onAnimationEnd(Animation animation) {
anim2.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) { }
@Override
public void onAnimationEnd(Animation animation) {
// 3.Lorsque l'animation descendante est terminée, redémarrez l'animation ascendante
view.startAnimation(anim1);
}
@Override
public void onAnimationRepeat(Animation animation) { }
});
// 2.Lorsque l'animation vers le haut est terminée, démarrez l'animation vers le bas
view.startAnimation(anim2);
}
@Override
public void onAnimationRepeat(Animation animation) { }
});
// 1.Lancer l'animation pour monter
view.startAnimation(anim1);
La double douleur de l'imbrication des rappels est que le processus que vous souhaitez effectuer et l'ordre dans lequel vous écrivez le code sont inversés, ce qui ne peut pas être fait.
C'est le seul cas où vous souhaitez utiliser Kotlin (il est préférable d'utiliser la bibliothèque
Comme @glayash l'a commenté, si vous répétez l'animation comme celle-ci, vous pouvez écrire comme suit, pour que cela ne devienne pas un enfer de rappel et que vous n'ayez même pas besoin d'utiliser Kotlin.
//Animation qui monte en 2 secondes
final TranslateAnimation anim1 = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, -0.1f);
anim1.setDuration(2000);
//Inverser et répéter indéfiniment
anim1.setRepeatMode(Animation.REVERSE);
anim1.setRepeatCount(Animation.INFINITE);
view.startAnimation(anim1);
C'est pourquoi je l'ai essayé avec Kotlin.
Tout d'abord, créez une "fonction qui exécute l'animation et passe à la suivante lorsque l'animation est terminée".
Ici, je l'ai défini comme une fonction d'extension de View
.
package net.amay077.animsample
import android.view.View
import android.view.animation.Animation
import kotlin.coroutines.experimental.suspendCoroutine
suspend fun View.startAnimationAsync(anim: Animation) {
return suspendCoroutine { continuation ->
anim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation?) { }
override fun onAnimationEnd(animation: Animation?) {
continuation.resume(Unit)
}
override fun onAnimationRepeat(animation: Animation?) { }
})
this.startAnimation(anim)
}
}
L'appelant ressemble à ceci:
C'est le paradis par rapport à Java dans Callback Hell ...
Il semble que vous deviez utiliser launch (UI) {}
au lieu de ```async () {} `` car l'animation doit être appelée depuis le thread de l'interface utilisateur.
val button1 = findViewById(R.id.button1)
val anim1 = TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, -0.5f)
anim1.duration = 2000
val anim2 = TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, -0.5f,
Animation.RELATIVE_TO_SELF, 0.0f)
anim2.duration = 2000
launch(UI) { //Je vais m'asynchroniser depuis le fil principal
//Répéter tout le temps
while (true) {
button1.startAnimationAsync(anim1) // 1.Lancer une animation qui monte sur 2 secondes
button1.startAnimationAsync(anim2) // 2.Exécutez une animation qui descend sur 2 secondes
}
}
C'est la première fois que j'utilise Kotlin correctement, alors je peux peut-être encore l'améliorer. .. Veuillez indiquer tout bon code.
Pour l'implémentation à Kotlin, je me suis référé au site suivant
C # (c'est-à-dire Xamarin.Android) peut également être obtenu avec une combinaison de «async / await (ie Task)» et «TaskCompletionSource».
C # a également une méthode d'extension qui peut être définie comme:
public static class ViewAnimationExtensions
{
public static Task<bool> StartAnimationAsync(this View view, Animation anim)
{
var source = new TaskCompletionSource<bool>();
EventHandler<Animation.AnimationEndEventArgs> handler = null;
handler = (sender, e) =>
{
anim.AnimationEnd -= handler; //N'oubliez pas de vous désinscrire
source.SetResult(true); //suite kotlin.resume(Unit)Toko
};
anim.AnimationEnd += handler; //Abonnez-vous à l'événement
view.StartAnimation(anim);
return source.Task;
}
}
C'est le côté de départ.
Ajoutez le mot-clé ʻawait`` au moment de l'appel, et ajoutez le mot-clé
ʻasync à la méthode qui le contient (ici` ʻOnCreate
).
protected async override void OnCreate(Bundle savedInstanceState)
{
/*réduction*/
while (true)
{
await button1.StartAnimationAsync(anim1);
await button1.StartAnimationAsync(anim2);
}
}
Ce serait bien si Kotlin pouvait être mélangé avec Java dans le même projet.
Recommended Posts