Blog

Débuter avec Material Design sur Android Lollipop

Voilà déjà quelques mois que Lollipop est sorti sur nos appareils Android, et pourtant les applis qui suivent les standards de Material Design sont encore rares. Voici donc quelques conseils pour mettre à jour vos applis!

Avant toute chose, je recommande de prendre un papier et un crayon (et même une paire de ciseaux) pour faire quelques essais. Il est en effet essentiel d’être très clair sur les effets qu’on souhaite ajouter avant de commencer à coder avec ses petits doigts. Pour ma part, j’ai réalisé une petite appli simple pour tester les concepts Material Design avec les éléments suivants:

  • une barre d’action, qui affiche un titre et des éventuels boutons contextuels
  • un ViewPager (qui permet de glisser l’écran à gauche/droite) et, bien évidemment, une barre de boutons qui affiche le titre des éléments disponibles et l’onglet sélectionné
  • chaque élément du ViewPager contient une liste d’éléments cliquables
  • le clic sur chaque élément (peu importe l’écran) affiche le détail de cet élément dans un cadre en surimpression.

En partant de ces éléments de navigation, il faut à présent décider de

  • quelles animations on veut mettre en avant
    • que se passe-t-il lorsqu’on scrolle la liste vers le bas? vers le haut?
    • que se passe-t-il lorsqu’on slide à gauche ou à droite dans le ViewPager?
    • que se passe-t-il quand on clique un élément d’une liste? quand on ferme le détail de cet élément?
  • quelle élévation on veut donner à chaque élément
    • C’est ici que la paire de ciseau se révèle utile. On découpe les petits papiers et on les fait bouger pour bien savoir lequel on met par dessus l’autre!
      material design layering

Roman Nurik propose une checklist de tout ce à quoi il faut penser pour passer en Material Design.

Au niveau des librairies disponibles, il y’en a déjà quelques unes.

Pour ma part, j’ai commencé par implémenter un SlidingTabLayout en suivant ces instructions. C’était super, j’en ai même profité pour apprendre à utiliser les Toolbars. MAIS ! ça ne bouge pas…

Dans un premier temps, j’ai ajouté un onTouchListener sur le scroll de mes ListViews. Pour plus de facilité d’écriture et de rétro-compatibilité, j’ai utilisé NineOldAndroid pour gérer les translationY.

        @Override
	public boolean onTouch(View v, MotionEvent event)
	{
		if(event.getAction() == MotionEvent.ACTION_DOWN)
		{
			mInity = event.getY();
		}
		else if(event.getAction() == MotionEvent.ACTION_MOVE)
		{
			float scrollY = event.getY() - mInity;
			// Pour bien caler son animation, utiliser des logs est une méthode simple et efficace!
			// Log.d("test", "y: "+event.getY() + " scrollY: "+scrollY);

			// On veut s'arrêter de déplacer la ToolBar si on arrive en haut
			if(scrollY < 0)
				ViewHelper.setTranslationY(toolbar, scrollY / 2);

			// Le SlidingTab, doit, en revanche, ne pas dépasser la hauteur de la toolbar en scroll vers le haut 
			//et ne doit jamais descendre par rapport à là où il se trouve au départ.
			if( scrollY> (-toolbar.getHeight()) && scrollY < 0)
				ViewHelper.setTranslationY(tabs, scrollY);
		}
		else if(event.getAction() == MotionEvent.ACTION_UP)
		{
			mInity = 0;
		}
		return false;
	}

Le but ici est de déplacer la ToolBar et le SlidingTab vers le haut lorsqu'on scrolle vers le haut dans la liste. Cependant, pour ajouter un peu de fluidité, la Toolbar et le SlidingTabs ne scrollent pas à la même vitesse, car je voulais que la ToolBar disparaisse entièrement et que le SlidingTabs reste à l'écran.

Pour bien caler son animation, il est souvent très utile de loguer les événements (event.getY()...)

Super! Maintenant, ça commence à bien bouger, et le tout en seulement quelques lignes!

Ensuite, je voulais animer le fond d'écran du header en fonction du scroll horizontal dans le ViewPager. En partant du même principe et en ajoutant un OnPageChangeListener sur le SlidingTab...

@Override
	public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
		if(positionOffsetPixels == 0)
			return;
		int blue = getResources().getColor(R.color.blue);
		int cyan = getResources().getColor(R.color.cyan);
		int green = getResources().getColor(R.color.green);
		int r1, g1, b1, r2, g2, b2;
		// Je vous passe les détails un peu fastidieux du calcul de la couleur en fonction de l'avancement dans le scroll horizontal!
		// le principe est le suivant: 
		// - on connait l'onglet selectionné grâce au paramètre "position"
		// - positionOffset donne un float qui correspond à un "pourcentage de scroll horizontal". 
		// On sait qu'on doit transitionner d'une couleur C1 à une couleur C2 et on sait que l'utilisateur a scrollé de x%. 
		// Il suffit de faire un peu de maths pour trouver la bonne couleur à afficher!

Ça commence à être joli!

Ensuite, je voulais concentrer mes efforts sur les fameux "sharedElement" dans les Transitions pour gérer une animation dans la barre d'action d'un titre. Et puis entre temps, j'ai découvert une librairie très sympa qui regroupe ça et fait plein d'autres choses, comme par exemple simplifier encore davantage les animations de scroll, l'apparation/disparition de la Toolbar.

Le code de mon appli de test est disponible ici. Attention, c'est un work in progress!

admin

Written by

The author didnt add any Information to his profile yet