Tour D Horizon Des Drawables

8,325 views
8,205 views

Published on

Published in: Technology
1 Comment
10 Likes
Statistics
Notes
No Downloads
Views
Total views
8,325
On SlideShare
0
From Embeds
0
Number of Embeds
64
Actions
Shares
0
Downloads
183
Comments
1
Likes
10
Embeds 0
No embeds

No notes for slide
  • L’objet de cette présentation : les Drawables !
    Pourquoi : tout simplement parce que je trouve que c’est une ressource inexploitée du framework Android !
    De plus peu de programmeurs ont une véritable connaissance des Drawables.
  • J’aimerai commencer par une petite note générale : Ne sachant pas trop comment organiser tout ça j’ai préféré rassembler les différentes petites remarques ici.
    Tout d’abord je me présente :
    - Je m’appelle Cyril Mottier, je suis ingénieur développement sur plateforme mobile (Android et iPhone : c’est cool de connaitre les deux car je peux comparer les défauts/avantages de chacunes des plateformes).
    - Je suis l’auteur d’un blog de développement francophone sur Android (pourquoi francophone? tout simplement parce qu’il y a rien de francophone ... pourtant j’aurais préféré faire de l’anglais)
    - Sur le Market, j’ai fait MetroMap Paris (que vous avez peut etre utilisé en venant ici à Paris :D).
    Pour information :
    - J’aimerai d’abord remercier toute l’organisation de m’avoir invité
    - La présentation a été fait un peu dans la précipitation donc il est possible que je m’aborde pas forcément bien les problématiques ou tout simplement que je parle mal/faussement ... Veuillez m’en excuser :).
    - N’hésitez pas à poser des questions durant la présentation si un point vous intrigue.
  • Je vous pose la question : « C’est quoi un Drawable ? »
    - D’un point de vue global, un Drawable désigne un objet qui peut être dessiné/affiché (traduction bête et méchante du nom anglais). Bizarrement, un texte pourrait être considéré comme un Drawable mais ça n’est pas le cas car il n’existe pas de TextDrawable ... à vous de le coder? :)
    - Dans le framework Android c’est un composant élémentaire puisque c’est le moyen privilégié pour afficher un composant graphique (image, gradient, etc.)
  • Je vous pose la question : « C’est quoi un Drawable ? »
    - D’un point de vue global, un Drawable désigne un objet qui peut être dessiné/affiché (traduction bête et méchante du nom anglais). Bizarrement, un texte pourrait être considéré comme un Drawable mais ça n’est pas le cas car il n’existe pas de TextDrawable ... à vous de le coder? :)
    - Dans le framework Android c’est un composant élémentaire puisque c’est le moyen privilégié pour afficher un composant graphique (image, gradient, etc.)
  • Je vous pose la question : « C’est quoi un Drawable ? »
    - D’un point de vue global, un Drawable désigne un objet qui peut être dessiné/affiché (traduction bête et méchante du nom anglais). Bizarrement, un texte pourrait être considéré comme un Drawable mais ça n’est pas le cas car il n’existe pas de TextDrawable ... à vous de le coder? :)
    - Dans le framework Android c’est un composant élémentaire puisque c’est le moyen privilégié pour afficher un composant graphique (image, gradient, etc.)
  • - Permet de gérer plus facile les différentes résolutions/densités (c’est cet objet qui gère partiellement - en coordoniation avec les layouts/vues - le redimensionnement)
    - Les Drawables facilitent l’utilisation de ressources graphiques tout en augmentant les possibilités :
    - Un contrôle précis de l’affichage par des propriétés avancées (setAlpha, setColorFilter, propriétés relatives à chaque Drawable comme la gravity ou tileMode sur un BitmapDrawable)
    - Possibilités variées grâce à l’architecture en pattern composite des Drawables (cf slide suivant)
    - Enfin les Drawables sont tellement bien intégré au système qu’il vous permette de modifier l’apparence globale des widgets Android sans même les étendre ou les réécrire (View.setBackground() par exemple).
  • - Arbre de la hiérarchie des Drawables : il y a des classes abstraites (Drawable, DrawableContainer, etc.) et le pattern Composite => un Drawable contient un Drawable
    - Une hiérarchie assez conséquente (environ 15 Drawables différents dont on peut trouver un exemple dans les sources relatives à cette présentation)
    - Une hiérarchie à l’instar de View, ViewGroup, etc. (des Drawable dans d’autres Drawables)
  • - Arbre de la hiérarchie des Drawables : il y a des classes abstraites (Drawable, DrawableContainer, etc.) et le pattern Composite => un Drawable contient un Drawable
    - Une hiérarchie assez conséquente (environ 15 Drawables différents dont on peut trouver un exemple dans les sources relatives à cette présentation)
    - Une hiérarchie à l’instar de View, ViewGroup, etc. (des Drawable dans d’autres Drawables)
  • - Arbre de la hiérarchie des Drawables : il y a des classes abstraites (Drawable, DrawableContainer, etc.) et le pattern Composite => un Drawable contient un Drawable
    - Une hiérarchie assez conséquente (environ 15 Drawables différents dont on peut trouver un exemple dans les sources relatives à cette présentation)
    - Une hiérarchie à l’instar de View, ViewGroup, etc. (des Drawable dans d’autres Drawables)
  • Et s’il vous plait : ne me faites pas de new dans le onDraw ... je vois ça trop souvent et ça m’horrifie :) ... J’aime désigner les développeurs comme les fautifs des plaintes du public fasse à Android : Si vous faites de la merde, c’est tout Android qui prend. VOUS êtes les promoteurs de cette superbe plateforme !
  • - Mon canvas n’est pas dans un état acceptable? (canvas.translate(2000, 2000) ...) => NON
    - J’ai zappé d’inclure ma vue dans le layout qui s’affiche => Ça m’arrive de temps à autre ... trop souvent même :D ... mais cette fois j’ai bien fait attention et ce n’est pas ça !
    - La solution ??? J’ai oublié de définir la taille de mon Drawable ! (setBounds).
  • - Mon canvas n’est pas dans un état acceptable? (canvas.translate(2000, 2000) ...) => NON
    - J’ai zappé d’inclure ma vue dans le layout qui s’affiche => Ça m’arrive de temps à autre ... trop souvent même :D ... mais cette fois j’ai bien fait attention et ce n’est pas ça !
    - La solution ??? J’ai oublié de définir la taille de mon Drawable ! (setBounds).
  • - Mon canvas n’est pas dans un état acceptable? (canvas.translate(2000, 2000) ...) => NON
    - J’ai zappé d’inclure ma vue dans le layout qui s’affiche => Ça m’arrive de temps à autre ... trop souvent même :D ... mais cette fois j’ai bien fait attention et ce n’est pas ça !
    - La solution ??? J’ai oublié de définir la taille de mon Drawable ! (setBounds).
  • - Mon canvas n’est pas dans un état acceptable? (canvas.translate(2000, 2000) ...) => NON
    - J’ai zappé d’inclure ma vue dans le layout qui s’affiche => Ça m’arrive de temps à autre ... trop souvent même :D ... mais cette fois j’ai bien fait attention et ce n’est pas ça !
    - La solution ??? J’ai oublié de définir la taille de mon Drawable ! (setBounds).
  • Commençons donc par définir quelques fonctionnalités inhérentes aux Drawables :
    - Un Drawable, comme nous venons de le voir, a un emplacement et une taille définie par setBounds(). Il est également possible de déterminer la taille «préférée» du Drawable ainsi que ça taille minimale (Dans le cas d’un Bitmap/NinePatchDrawable c’est équivalent)
    - Un Drawable peut également avoir un état courant et un niveau courant : cette fonctionnalité n’est pas utilisée dans l’intégralité des Drawables mais nous y reviendront dans la suite de cette présentation.
    - Enfin, puisque les Drawables sont des entités graphiques, il est possible de modifier leur aspect lors du rendu comme le niveau de transparence, tramage ou non, etc.
  • - Pour s’animer, bouger, tourner, etc .. en clair changer, un Drawable doit pouvoir se redessiner. Or cette fonction est propre à la classe View (méthode invalidate() et postInvalidate()). C’est donc l’utilité de la méthode invalidateDrawable() de Drawable.Callback.

    - Un Drawable dispose d’une référence sur une classe qui implémente Drawable.Callback. Il s’avère que View implémente cette dernière et fournit une méthode d’aide : verifyDrawable(Drawable). Lorsqu’un Drawable «veut» s’invalider, il appelle invalidateDrawable(). La classe View implémente cette méthode et effectue un invalidate() ssi verifyDrawable(d) renvoie vrai.
  • Le code c’est cool mais Android apporte une fonctionnalité très intéressante qui consiste à définir par des fichiers XML toutes entités relative à l’UI. Les Drawables ne dérogent pas à la règles!
  • Le code c’est cool mais Android apporte une fonctionnalité très intéressante qui consiste à définir par des fichiers XML toutes entités relative à l’UI. Les Drawables ne dérogent pas à la règles!
  • C’est inutile de faire ça parce que ça revient à faire un getDrawable(R.drawable.pattern) (mode par défaut).
  • C’est inutile de faire ça parce que ça revient à faire un getDrawable(R.drawable.pattern) (mode par défaut).
  • En mode « clamp », les arêtes droites et inférieures sont répétées pour remplir l’intégralité des «bounds»
  • Via XML il sert à rien .... :(
  • Via XML il sert à rien .... :(
  • Via XML il sert à rien .... :(
  • Via XML il sert à rien .... :(
  • Via XML il sert à rien .... :(
  • Via XML il sert à rien .... :(
  • C’est l’implémentation la plus aboutie que je connaissent des image étirables :
    - sous iPhone : symétrique et sur les arêtes ..
    - en CSS3 : sur les arêtes

    En Android ; c’est des N-patchs ! (zones étirables multiples) et proportionnellement étirées. Surtout : l’information des zones étirables et du padding et incluses DANS l’image ! C’est parfait alors que sous iPhone, cette information est dans le code ...
  • Montrer que le splash screen de MetroMap Paris peut être réalisé à l’aide d’un unique FrameLayout !!!! (poussé à l’extrême)
  • Bien préciser que j’ai fait celui là dans la précipitation et donc que le système est loin d’être parfait ... Mais l’idée est là :)
  • - En savoir plus : sur le même sujet, vous pourrez découvrir un article expliquant comment créer ses propres boutons (StateListDrawable) et un autre sur les nine-patch (NinePatchDrawable). Beaucoup d’articles divers pour rendre vos UI rapides et belles : pour résumer faire de vos UI un succès !
    - Code source :
    - Avoir accès au code source d’Android est une merveilleuse opportunité de bien s’approprier la plateforme. N’hésitez pas à faire un tour dedans ... je vais même faire suivre la bonne parole des Googlers : Aidez les en soumettant vos patchs !
    - GitHub : le code source de l’application de démonstration est disponible sur ce site.
  • Voilà ! C’est fini ... j’espère avoir répondu à vos attentes et surtout vous avoir montrer de nouvelles facettes inexploitées du système Android. H’hésitez pas à poser vos questions !
    Bien sûr je serais disponible par la suite si vous le souhaitez pour répondre à des questions dans un mode plus « privé ».
  • Tour D Horizon Des Drawables

    1. 1. Tour d’horizon des Drawables Dessiner c’est gagner !!!
    2. 2. Note générale 2
    3. 3. Introduction Le B.A.-ba des Drawables 3
    4. 4. Introduction C’est quoi un Drawable? 4
    5. 5. Introduction C’est quoi un Drawable? • Entité qui peut être « dessinée » • Une forme, un gradient, une image, un 9- patch, etc. 4
    6. 6. Introduction C’est quoi un Drawable? • Entité qui peut être « dessinée » • Une forme, un gradient, une image, un 9- patch, etc. • Composant essentiel du SDK Android 4
    7. 7. Introduction C’est quoi un Drawable? • Entité qui peut être « dessinée » • Une forme, un gradient, une image, un 9- patch, etc. • Composant essentiel du SDK Android • Instanciable en Java ou XML 4
    8. 8. Introduction Pourquoi est-ce si important? • Gestion du multi-device facilitée • Abstraction de ce qui est « dessinable » • Plus simple d’utilisation • Plus évolué que les Bitmaps ! • Possibilité de modifier des widgets sans les étendre 5
    9. 9. Introduction Architecture 6
    10. 10. Introduction Architecture Drawable 6
    11. 11. Introduction Architecture Drawable ColorDrawable GradientDrawable 6
    12. 12. Introduction Architecture Drawable ColorDrawable GradientDrawable LayerDrawable 6
    13. 13. « How-to » basique Hello Drawables ! 7
    14. 14. « How-to » basique Premier essai private Drawable mDrawable; public DrawableView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mDrawable = context.getResources().getDrawable(R.drawable.my_drawable); } public void onDraw(Canvas canvas) { super.onDraw(canvas); mDrawable.draw(canvas); } 8
    15. 15. « How-to » basique Gné ? Ça marche pas ! 9
    16. 16. « How-to » basique Gné ? Ça marche pas ! • Mon Canvas n’est pas dans un état « acceptable » ? 9
    17. 17. « How-to » basique Gné ? Ça marche pas ! • Mon Canvas n’est pas dans un état « acceptable » ? • J’ai oublié de mettre la vue dans mon layout ? 9
    18. 18. « How-to » basique Gné ? Ça marche pas ! • Mon Canvas n’est pas dans un état « acceptable » ? • J’ai oublié de mettre la vue dans mon layout ? • .... Je n’ai pas définit la taille de mon Drawable 9
    19. 19. « How-to » basique Gné ? Ça marche pas ! • Mon Canvas n’est pas dans un état « acceptable » ? • J’ai oublié de mettre la vue dans mon layout ? • .... Je n’ai pas définit la taille de mon Drawable • setBounds(), getIntrinsic[Width/Height]() 9
    20. 20. « How-to » basique La solution ! private Drawable mDrawable; public DrawableView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mDrawable = context.getResources().getDrawable(R.drawable.my_drawable); mDrawable.setBounds(0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()); } public void onDraw(Canvas canvas) { super.onDraw(canvas); mDrawable.draw(canvas); } 10
    21. 21. Les fonctionnalités Ça permet quoi les Drawables? 11
    22. 22. Quelques fonctionnalités Généralités • Emplacement / taille : • setBounds(), getIntrinsic[Width/Height] (), getMinimum[Width/Height](), etc. • Etat courant : • setState(), state_[pressed/focused/...], setLevel(), etc. • Affichage : setAlpha(), setDither(), ... 12
    23. 23. Quelques fonctionnalités Drawable.Callback • Un Drawable doit pouvoir « s’invalider » • Utilité de l’interface Drawable.Callback • View implémente Drawable.Callback • Méthode d’aide verifyDrawable() 13
    24. 24. Quelques fonctionnalités Drawable.Callback public class DrawableView extends View { private Drawable mDrawable; public DrawableView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mDrawable = context.getResources().getDrawable(R.drawable.my_drawable); mDrawable.setBounds(0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()); } @Override protected boolean verifyDrawable(Drawable who) { return who == mDrawable || super.verifyDrawable(who); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mDrawable.draw(canvas); } } 14
    25. 25. Principe d’état constant Problématique private static final int OPAQUE = 255; private static final int TRANSLUCENT = 70; Book book = ...; TextView listItem = ...; listItem.setText(book.getTitle()); Drawable star = getContext().getResources().getDrawable(R.drawable.star); if (book.isFavorite()) { star.setAlpha(OPAQUE); } else { star.setAlpha(TRANSLUCENT); } Extrait de http://www.curious-creature.org/2009/05/02/drawable-mutations/ 15
    26. 26. Principe d’état constant Explication du phéomène • Android « factorise » les états des Drawables • Minimise l’empreinte mémoire 16
    27. 27. Principe d’état constant Explication du phéomène 17
    28. 28. Principe d’état constant Explication du phéomène Drawable Drawable 17
    29. 29. Principe d’état constant Explication du phéomène Drawable Drawable ConstantState 17
    30. 30. Principe d’état constant Explication du phéomène Drawable Drawable ConstantState 17
    31. 31. Principe d’état constant Résolution du « problème » • Pas de fonctionnalité « copy-on-write » • Utilisation de la méthode mutate() : • Copie de l’état constant • Mise du flag mMutated à true • Appel multiple à mutated() sans effet 18
    32. 32. Principe d’état constant Résolution du « problème » Drawable Drawable 19
    33. 33. Principe d’état constant Résolution du « problème » Muté Muté Drawable Drawable ConstantState ConstantState 19
    34. 34. Principe d’état constant Résolution du « problème » Muté Muté Drawable Drawable ConstantState ConstantState 19
    35. 35. Principe d’état constant Résolution du « problème » private static final int OPAQUE = 255; private static final int TRANSLUCENT = 70; Book book = ...; TextView listItem = ...; listItem.setText(book.getTitle()); Drawable star = getContext().getResources().getDrawable(R.drawable.star); if (book.isFavorite()) { star.mutate().setAlpha(OPAQUE); } else { star.mutate().setAlpha(TRANSLUCENT); } Extrait de http://www.curious-creature.org/2009/05/02/drawable-mutations/ 20
    36. 36. Instanciation Enfin les travaux pratiques ! 21
    37. 37. Instancier un drawable Le résultat voulu 22
    38. 38. Instancier un drawable Le résultat voulu 22
    39. 39. Instancier un drawable Deux possibilités : Java ... float density = getContext().getResources().getDisplayMetrics().density; // gradient from #4e525c to #31343c int[] colors = new int[] {Color.rgb(78, 82, 92), Color.rgb(49, 52, 60)}; GradientDrawable gradient = new GradientDrawable(Orientation.BOTTOM_TOP, colors); gradient.setShape(GradientDrawable.OVAL); gradient.setStroke((int) (3 * density), Color.WHITE, 4 * density, 5 * density); 23
    40. 40. Instancier un drawable ... et XML <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <gradient android:startColor="#4e525c" android:endColor="#31343c" android:angle="90" /> <stroke android:width="3dip" android:color="#fff" android:dashWidth="4dip" android:dashGap="5dip" /> </shape> 24
    41. 41. Drawable Listing em o D Code disponible sur http://www.github.com/cyrilmottier/DrawablePresentation 25
    42. 42. BitmapDrawable • Très largement utilisé • Pourtant méconnu / mal connu • Souvent utilisé tel quel • context.getResources().getDrawable(R.drawable.image) (où image est un fichier de type png ou jpg) • Contrôles plus poussés disponibles • tileMode, gravity, etc. 26
    43. 43. BitmapDrawable android:tileMode <?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http:// schemas.android.com/apk/res/android" android:src="@drawable/pattern" /> 27
    44. 44. BitmapDrawable android:tileMode <?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http:// schemas.android.com/apk/res/android" android:src="@drawable/pattern" /> 27
    45. 45. BitmapDrawable android:tileMode <?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http:// schemas.android.com/apk/res/android" android:src="@drawable/pattern" android:tileMode="clamp" /> 28
    46. 46. BitmapDrawable android:tileMode <?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http:// schemas.android.com/apk/res/android" android:src="@drawable/pattern" android:tileMode="repeat" /> 29
    47. 47. BitmapDrawable android:tileMode <?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http:// schemas.android.com/apk/res/android" android:src="@drawable/pattern" android:tileMode="mirror" /> 30
    48. 48. BitmapDrawable android:gravity <?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http:// schemas.android.com/apk/res/android" android:src="@drawable/pattern" android:gravity="center" /> 31
    49. 49. BitmapDrawable android:gravity <?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http:// schemas.android.com/apk/res/android" android:src="@drawable/pattern" android:gravity="top|right" /> 32
    50. 50. NinePatchDrawable Mon préféré héhé ! 33
    51. 51. NinePatchDrawable Mon préféré héhé ! • Instanciation simple : • getDrawable(R.drawable.image) (image ayant l’extension .9.png) • Concept d’image « étirable » 33
    52. 52. NinePatchDrawable Mon préféré héhé ! 34
    53. 53. StateListDrawable • Présent partout : • Boutons • Checkboxes • Changement de l’apparence fonction de l’état courant 35
    54. 54. Dernière démos On finit en beauté ? 36
    55. 55. A quoi ça sert tout ça? Flatten Hierarchy em o D Code disponible sur http://www.github.com/cyrilmottier/DrawablePresentation 37
    56. 56. Créer son Drawable • Étendre de Drawable (ou une classe fille) • Définir les méthodes abstraites • setAlpha, setColorFilter, draw, etc. • Redéfinir si nécessaire 38
    57. 57. RemoteDrawable em o D Code disponible sur http://www.github.com/cyrilmottier/DrawablePresentation 39
    58. 58. Références • En savoir plus : • http://android.cyrilmottier.com • Code source : • http://android.git.kernel.org/ • http://github.com/cyrilmottier 40
    59. 59. Des questions ? N’hésitez pas ! 41

    ×