Dans ce chapitre, nous allons voir comment améliorer encore plus l'expérience utilisateur (UX) en ajoutant quelques animations à notre application. Le but est de la rendre vraiment agréable à utiliser...
Les animations étant une part importante du Material Design, je vous conseille de jeter un coup d'œil à la documentation de Google ainsi qu'à ce cours expliquant très bien les objectifs et enjeux des animations.
Créez de belles transitions
Sur Android, on parle généralement de transition quand on passe d'un écran à un autre. Dans notre cas, nous souhaitons qu'une transition s'opère quand nous cliquons sur un élément de notre RecyclerView pour arriver à l'écran de Détail d'un projet "design".
Pour réaliser cela, nous utiliserons le concept de "Shared Element" : un élément graphique de notre interface graphique sera partagé entre plusieurs écrans lors d'une animation.
Dans un premier temps, nous allons définir dans le layout des deux écrans concernés, la vue que nous souhaitons partager.
Extrait de strings.xml :
...
<!-- ANIMATION -->
name="animation_main_to_detail" translatable="false"AnimationMainToDetail
Explications : Nous créons ici une valeur texte permettant d'identifier précisément le nom de notre animation.
Extrait de fragment_main_item.xml :
<?xml version="1.0" encoding="utf-8"?>
...
android:id="@+id/fragment_main_item_image"
android:transitionName="@string/animation_main_to_detail"
...
Extrait de fragment_detail.xml :
...
android:id="@+id/fragment_detail_image"
android:transitionName="@string/animation_main_to_detail"
...
...
Explications : Grâce à l'attribut android:transitionName
, nous définissons le même identifiant pour les deux vues qui se partageront une animation.
Maintenant, nous allons modifier notre fragment MainFragment
afin d'activer l'animation de transition.
Extrait de MainFragment.java :
public class MainFragment extends BaseFragment {
...
private void configureRecyclerView(){
...
ItemClickSupport
.addTo(recyclerView, R.layout.fragment_main_item)
.setOnItemClickListener((rv, position, v) -> this.navigateToDetail(this.projectAdapter.getProject(position), v));
...
}
...
private void navigateToDetail(Project project, View viewClicked){
...
// Start Animation
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(getActivity(), viewClicked, getString(R.string.animation_main_to_detail));
startActivity(intent, options.toBundle());
} else {
startActivity(intent);
}
}
}
Explications : Nous avons modifié notre méthode navigateToDetail()
afin d'ajouter une nouvelle animation au lancement de notre activité DetailActivity
(et par conséquent, son fragment DetailFragment) grâce à la méthode makeSceneTransitionAnimation
.
Cette dernière méthode n'étant disponible qu'à partir de la version Lollipop (Material Design), nous vérifions que l'appareil sur lequel s'exécute notre application est bien supérieur à la version 5 d'Android.
Et c'est tout ! Exécutez votre application. Votre animation de transition s'effectue parfaitement...
Animez des vues
Jusqu'ici, nous avons animé la transition d'un écran à un autre. Cependant, nous n'avons toujours pas vu comment animer nos vues habituelles, comme par exemple les TextView
ou encore les Button
...
Ainsi, nous allons immédiatement créer trois méthodes nous permettant d'animer différentes vues au moyen de différentes techniques, le tout dans notre classe DetailFragment
.
private void scaleViewAnimation(View view, int startDelay){
// Reset view
view.setScaleX(0);
view.setScaleY(0);
// Animate view
view.animate()
.scaleX(1f)
.scaleY(1f)
.setInterpolator(new FastOutSlowInInterpolator())
.setStartDelay(startDelay)
.setDuration(500)
.start();
}
Explications : Cette première méthode permettra de créer une animation d'effet d'échelle sur une vue. La méthode animate()
appliquée à un objet de type View
retourne un objet de type ViewPropertyAnimator
permettant d'exécuter différentes types d'animations sur la vue en question.
Dans notre cas, nous utilisons les méthodes scaleX
et scaleY
afin de créer un "grossissement" de notre vue. La méthode setInterpolator()
permet d'indiquer la manière dont l'animation sera jouée. Et enfin, nous définissons une durée et un délai avant exécution à notre animation grâce aux méthodes correspondantes.
private void alphaViewAnimation(View view, int startDelay){
Animation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setDuration(1000);
animation.setStartOffset(startDelay);
view.startAnimation(animation);
}
private void fromBottomAnimation(View view, int startDelay) {
Animation animation = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, +1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
animation.setDuration(1000);
animation.setInterpolator(new AccelerateInterpolator());
animation.setStartOffset(startDelay);
view.startAnimation(animation);
}
Explications : Ces deux dernières méthodes utilisent l'objet Animation afin de créer des animations qui seront exécutées cette fois-ci par la méthode startAnimation
d'une vue.
La première méthode crée une animation de type AlphaAnimation
. Cette dernière permettra de faire apparaître progressivement à l'écran la vue concernée par l'animation.
La seconde méthode permettra de faire apparaître une vue du bas de l'écran vers sa position initiale, grâce à l'animation TranslateAnimation
.
Testons toutes ces belles animations immédiatement dans notre code !
Extrait de DetailFragment.java :
public class DetailFragment extends BaseFragment {
...
private void updateDesignWhenStarting(){
...
this.animateViews();
}
...
private void animateViews(){
this.alphaViewAnimation(this.titleProject, 200);
this.scaleViewAnimation(this.fabButton, 500);
this.alphaViewAnimation(this.descriptionProject, 400);
this.alphaViewAnimation(this.viewsProject, 500);
this.alphaViewAnimation(this.likesProject, 600);
this.alphaViewAnimation(this.commentsProject, 700);
this.fromBottomAnimation(this.shareButton, 800);
}
...
}
Explications : Nous avons créé la méthode animateViews()
appelant les méthodes précédemment créées qui nous permettent d'animer nos vues. Elle sera également appelée au démarrage de notre fragment.
Lancez votre application, et appréciez le résultat !