Tailles et densités sous Android

 

Note : cet article est encore en cours de rédaction. 

Si vous êtes intégrateur/développeur Android, vous vous êtes déjà pris la tête avec ça… Et avec la nécessité de rendre ses sites web responsive, c'est au tour des développeurs web de s'arracher les cheveux ! Comment faire en sorte qu'une application s'affiche correctement sur tous les devices ? Quelle est la vraie taille d'un écran ?

En effet, pour deux devices annonçant 800px de large (par exemple un Nexus 7 et un Samsung Note), l'affichage sera différent, car la densité n'est pas la même !

Encore mieux. Vous testez votre site internet sur un écran de Samsung Galaxy S2 qui annonce fièrement ses 480px de large. Sauf que votre image de 480px déborde de l'écran !

Il existe des milliers de devices sous Android, avec des tailles d'écran différentes. De la tablette à la montre connectée… Le challenge est de réaliser une application qui s'affiche correctement sur tous.

Et il y a de quoi se perdre entre pouces, pixels, dpi, dip… Commençons par un petit point sur les différentes unités utilisées.

Quelques définitions

On distingue les unités physiques : ce sont des dimensions concrètes, physiquement mesurables (mm, in, pt, px) des unités virtuelles, non directement mesurables, qui permettent de s'affranchir du type d'appareil.

Résolution : nombre de pixels disponibles sur l'affichage. Ex 480 x 800 pour un Samsung Galaxy S2

Densité : combien de pixels s'affichent dans une zone de taille constante de l'affichage. Unité : dots per inch = dpi
La valeur Screen density est le ratio de la résolution et de la taille d'affichage.
Ex : sur un écran à 240 dpi, il faut 240 pixels pour faire un pouce
On voit également fréquemment une autre unité, le ppi (pixels per inch). J'ai eu beaucoup de mal à saisir la différence. En fait les dpi sont des valeurs générales (théoriques, un genre de catégories, équivalent de mpdi, xdpi…) tandis que les ppi sont une valeur réelle (on parle de densité hardware)

Taille : quantité d'espace physique disponible pour afficher une interface. Unité : diagonale de l'écran en pouces (inch)
Android a groupé toutes les tailles d'écran en 4 grandes catégories : small, normal, large, and extra-large

Density-independent pixel : pixel virtuel indépendant de la densité de l'écran. La plus utilisée dans Android, c'est la taille en pixels qu'aurait l'interface sur un écran à 160 dpi. Unité : dp ou dip
On parle aussi de clientWidth

Scale-independent pixel = sp
Cette taille est basée sur les dp. Utilisé pour les textes.

android-screens-ranges

Densités

Dans le cas d'un développement Android, il faut désormais prévoir 5 versions pour toutes ses icônes (je dis 5 parce que le ldpi, on peut désormais laisser tomber). Voir en fin d'article pour les dimensions…

Classe Nom Densité Facteur Conversion Dossier drawable
ldpi low density 120 dpi 3/4 sp = 3/4 * dp drawable-ldpi
mdpi medium density 160 dpi 1 sp = dp drawable-mdpi
hdpi high density 240 dpi 1.5 sp = 1.5 x dp drawable-hdpi
xhdpi extra high density 320 dpi 2 sp = 2 x dp drawable-xhdpi
xxhdpi extra extra high density 480 dpi 3 sp = 3 x dp drawable-xxhdpi
xxxhdpi extra extra extra high density 640 dpi 4 sp = 4 x dp drawable-xxxhdpi

Le mdpi est considéré comme la baseline, c'est à dire la densité de base.

Tailles et résolutions d'écrans

Le Samsung Galaxy S2 est donc considéré comme un écran de taille normale (on est contents pour lui).

Taille ldpi (120) mdpi (160) hdpi (240)  xhdpi (320)
small QVGA (240×320) 480×640
normal WQVGA400 (240×400)
WQVGA432 (240×432)
HVGA (320×480) WVGA800 (480×800)
WVGA854 (480×854)
600×1024
640×960
large WVGA800 (480×800)
WVGA854 (480×854)
WVGA800 (480×800)
WVGA854 (480×854)
600×1024
xlarge 1024×600 WXGA (1280×800)
1024×768
1280×768
1536×1152
1920×1152
1920×1200
2048×1536
2560×1536
2560×1600

 

Quelques exemples d'appareils

Appareil Android Taille clientWidth Resolution screen.width devicePixelRatio  densité ppi
Samsung Galaxy Ace 2.2 3,5 » 320×480 mdpi 165
Nexus S 4.1.1  API 16 4″ 320 dips 480×800 480 px 1.5 hdpi 233
Samsung Galaxy S2 2.3.7 API 10 4,3″ 320 dips 480×800 480 px 1.5 hdpi 217
Moto X 4.4.2 API 19 360 dips 720×1280 360 px 2 xhdpi 312
Galaxy Nexus 4.3 360 dips 720×1280 360 px (?) 2 xhdpi 315
Nexus 4 4.2.2 API 17 4″ 384 dips 768×1280 384 px (?) 2 xhdpi 318
Nexus 4 4.3 API 18 4″ 360 dips 768×1280 768 px 2 xhdpi 318
Nexus 7 2012 4.4.2 API 19 7″ 601 dips 800×1280 601 px 1.331 hdpi 216
Nexus 7 2013 4.4.2 API 19 7″ 600 dips 1200×1920 1200 px 2 xhdpi 323
Samsung  Galaxy Note 4.1.1 API 16 5,3″ 400 dips 800×1280 800 px 2 xhdpi 285
Samsung  Galaxy S3 4.3 API 18 720×1280 2 xhdpi 306
Nexus 5 4.4.2 API 19 5″ 360 dips 1080×1920 3 xxhdpi 455
Samsung Galaxy S4 4.4.4 API 19 5″ 360 dips 1080×1920 3 xxhdpi 441
Nexus 5X 6.0 API 23 5,2″ 411 dips 1080×1920 3 xxhdpi 423
Samsung Galaxy S5 4.4.4 API 19 5,1″ 1080×1920 3 xxhdpi 432
Samsung Galaxy Note 4 4.4.4 API 19 480 dips 1440×2560 3 xxhdpi 515
LG G3 5,5″ 360 dips 1440×2560 4 xxxhdpi 538
Samsung Galaxy S6, S6 Edge, S7 5,1″ 1440×2560 4 xxxhdpi 577
Samsung Galaxy S8  7.0 5,8″ 1440×2960 4 xxxhdpi 571
Xperia Z5 Premium  5.1 5,5″ 2160×3840 xxxhdpi 806

Plus les pixels sont serrés, plus l'image est belle… On disait que l'oeil nu ne pouvait identifier des densités supérieures à 300 ppi. Et puis sont arrivés les devices xxxhdpi (le Nexus 5, le Nexus 6, LG G3). Là, c'est carrément de la super haute résolution.

Quand on voit ce tableau, on comprend mieux certaines choses :

  • une tablette Nexus 7 (modèle 2012), donc quelque chose d'assez large (taille 7 pouces) avec sa résolution de 800 x 1280 aura le même nombre de ppi qu'un petit Samsung Galaxy S2 de 4,3″ et 480 x 800.
  • Alors que si on compare cette même Nexus 7 à un Samsung  Galaxy Note : la résolution des deux appareils est la même (800 x 1280), mais les pixels seront beaucoup plus serrés sur les 5,3″ du Galaxy Note, le résultat sera donc plus agréable à l'oeil sur ce dernier.

A noter que le record de clientWidth en smartphone Android est actuellement détenu par le Google Nexus 6P : 412 dips. Tandis qu'on peut considérer que le plus bas est 320dips (mon Samsung Galaxy S2). Donc, pour afficher un site web sur un device Android en orientation portrait, garder en mémoire une fourchette de largeurs allant de 320 à 412px. Au-delà, on est en paysage, ou sur une tablette.

Voici l'illustration avec des émulateurs Genymotion et une application que je suis en train de développer. On va s'intéresser au player sur fond noir semi-transparent en bas de chaque écran.

application-sur-nexus-s-480x800 application-sur-nexus-7-800x1280

A gauche un émulateur Nexus S (caractéristiques équivalentes à mon Galaxy S2 : 480×800, hdpi donc densité 1.5 soit une largeur réelle de 320 dips). A droite, l'émulateur de la tablette Nexus 7 (800×1280, hdpi aussi).

Ces deux devices ont une densité théorique de 240 dpi (1,5 fois 160). Donc, comme j'ai défini sur la charte graphique que les boutons play et avance devaient mesurer 30dp, ils sont affichés avec une taille de 45px (1,5 fois 30). Et Android est allés les chercher dans le répertoire drawable-hdpi/

La tablette mesure 800px de large (soit 601 dips) contre 480px (soit 320 dips), donc elle offre presque deux fois plus d'espace pour le mon player s'étale. C'est pour cette raison que c'est tout tassé dans le player affiché dans le Nexus S : le « now playing » est sur 3 lignes, le compte à rebours sur 2 lignes… pas terrible !

application-sur-galaxy-note-800x1280 application-sur-nexus-7-800x1280

2e exemple. A gauche, un émulateur Samsung Galaxy Note. A droite, toujours la tablette Nexus 7. Cette fois-ci, les deux ont une résolution de 800×1280. Mais le Galaxy Note a une densité théorique de 320 dpi (xhdpi).

Mes boutons play et avance définis à 30dp sont donc affichés avec une taille de 60px sur le Galaxy Note. Et là, Android est allé les chercher dans drawable-xhdpi. C'est pourquoi ils apparaissent plus grands (mais pas pixellisés pour autant).

De même, si on ramène la largeur en dips (clientWidth), on a 601 dpi pour le Nexus 7 (à droite) et 400 dpi (à gauche) pour le Galaxy Note. On comprend pourquoi les éléments du player semblent bien plus au large dans la fenêtre du Nexus 7.

Pour l'imageView qui affiche la photo de la sleeve, j'ai défini comme largeur wrap_content. Les photos importées font 100px sur les deux devices.

J'ai également fait un test avec un émulateur Nexus 4 (768px de large, 320 dpi donc 360 dips) et l'émulateur Samsung Galaxy Note (800px de large, 320 dpi donc 400 dips). A cause de ces 80 dips de différence, on n'est plus assez large : sur le Nexus 4 je me retrouve encore avec le compte à rebours sur 2 lignes !

 

Comment accéder aux valeurs

En java

Selon la version du SDK, le code n'est pas le même…

screen.width

public static int getWindowWidth(Context context){
 int width;

if(android.os.Build.VERSION.SDK_INT >= 13) {
 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
 width = wm.getDefaultDisplay().getWidth();
 }
 else {
 width = context.getResources().getDisplayMetrics().widthPixels;
 }
 return width;
 }

Densité en dpi

density = context.getResources().getDisplayMetrics().densityDpi;

devicePixelRatio

devicePixelRatio= context.getResources().getDisplayMetrics().density;

On a également accès à une autre valeur, la scaledDensity, qui renvoie la même chose sur tous les devices que j'ai testés. J'ignore quelle est la différence…

La densité de pixels (les dpi ou les ppi)

xdpi = context.getResources().getDisplayMetrics().xdpi;

Et pour obtenir la densité verticale, utiliser la propriété ydpi.

Sur un vrai device, on récupère les ppi (217 ppi pour mon Samsung Galaxy S2). Sur un émulateur, on récupère les dpi (240 , 360…)

La valeur de référence

Plutôt que de saisir 160 en dur, on peut récupérer la valeur de la baseline (les 160 dpi) avec cette constante

DisplayMetrics.DENSITY_DEFAULT

En javascript (dans une webview en Cordova, ou le navigateur pour un site)

  • screen.width renvoie la résolution horizontale en pixels  (mais en fait, pas toujours… sous les versions d'Android inférieures à 4.4, on obtient le clientWidth !).
  • window.devicePixelRatio renvoie le ratio entre les pixels et les dips
  • document.documentElement.clientWidth donne la densité en dips (certains disent la taille du viewport), c'est à dire la vraie largeur disponible

Quelques formules

Calcul du devicePixelRatio

Formule : physical pixels / dips

Calcul des dpi

Formule : 160 x devicePixelRatio

Calcul de la « vraie » densité de pixels (les ppi) ou densité hardware

Pour calculer la densité de pixel d'un écran, on part de sa résolution (l pixels de large x L pixels de long) pour obtenir sa diagonale (remember Pythagore ?), et de sa taille t en pouces.

Formule : √(l² + L²) / t

Ex

  • pour un écran de tablette Retina de 9,7′ titrant 2048 x 1536 pixels : √(2048² + 1536²) / 9,7 = 264 ppi
  • pour mon écran de Samsung Galaxy S2 de 4,3′ titrant 480 x 800 : √(480² + 800²) / 4,3 = 217 ppi

Retrouvez une liste assez complète (mais qui commence à être ancienne) de devices et de leurs ppi

Sur dpiLove, vous avez même un outil de calcul en ligne de ces ppi

Density Independant Pixels (clientWidth)

Ou dip. Ne pas confondre avec les dpi !

Formule : pixels x 160/ dpi (ou pixels / devicePixelRatio)

Ex pour le Samsung Galaxy S2 ou le Nexus S : 480 x 160 / 240 = 320 dip

Et pour obtenir la largeur en pixels : dp * dpi / 160

Scale Independant Pixels

Formule 1 dp = f x sp

Selon la situation, f  est le facteur

  • d'agrandissement du texte choisi par l'utilisateur dans Paramètres > Accessibilité > Taille de police (normal par défaut)
  • par rapport à la baseline de 160 dpi (un hdpi, soit 240 dpi, c'est 1,5x plus que le mdpi qui est considéré comme la valeur de base)

Une police taille 42 pt dans Photoshop, utilisée sur un écran xxhdpi de 480 dpi reviendra à du 14 sp. Car 1sp = 3pt pour cette densité.

Tailles des icônes

Là encore, jolie prise de tête. Selon qu'on souhaite utiliser une image comme icône de menu, de lancement ou d'actionbar, la taille sera différente.

ldpi mdpi hdpi xhdpi xxhdpi xxxhdpi
Echelle 1 x 1 x 1.5 x 2 x 3 x 4 x
DPI 120 dpi 160 dpi 240 dpi 320 dpi 480 dpi 640 dpi
Icône de lancement 36 px 48 px 72 px 96 px 144 px 192 px
Icône pour Action bar, boîtes de dialogue, onglets 24 px 32 px 48 px 64 px 96 px 128 px
Petites icônes (contextuelles) 16 px 16 px 24 px 32 px 48 px 64 px
Icônes de barre de notification  18 px 24 px 36 px 48 px 72 px 96 px

Au fait, une icône d'action bar Holo Light, est de couleur #666666 avec une transparence de 60%

 

 

Sources

Understanding Density Independence in Android

Android Icon Size Guide Made Simple

Android: Screen Densities, Sizes, Configurations, and Icon Sizes

Une liste de devices avec leur résolution en pixels per inch

Une autre liste de devices avec leurs dimensions physiques, leur devicePixelRation et leur ppi

Calculer la densité de pixels de son écran

Mesurer la taille de son viewport

Developpez.com РLes unit̩s de mesure

Karine SANCHE

Partager cet article