La diffusione di Android su dispositivi molto eterogenei ha fatto la fortuna di questo sistema operativo, permettendogli di dimostrare le sue doti di
adattamento. Ma come sappiamo ha creato non pochi grattacapi agli sviluppatori. Uno degli aspetti più delicati, infatti, è la necessità di adattare il layout al
display.
Nel capitolo relativo alle risorse, si è spiegato come l'unità di misura da preferire sia il Density-Indipendent Pixel, in sigla dp, che rappresenta un
pixel non vincolato dalla densità del display. Proprio questo concetto di densità, intesa come rapporto tra numero di
pixel e dimensioni dello schermo, ha assunto un ruolo di primo piano, prevaricando in importanza sia la risoluzione che la misura dello schermo.
Il passo concettuale doveroso, a questo punto, è l'abbandono della visione “pixel-centrica” delle misure proprio perchè questa non tiene conto della densità
di popolazione dei pixel nel display. Definire le misure in pixel per gli elementi dei layout comporterebbe una visualizzazione molto diversa tra schermi a
bassa densità (dove le immagini verrebbero allargate) e quelli ad alta densità (dove le immagini risultarebbero rimpicciolite). La densità viene misurata in dpi ed il livello di 160 dpi (densità media o mdpi) rappresenta il punto di equilibrio. A questo
livello, un pixel equivale ad un dp.
Gli altri livelli comuni per le densità sono:
- ldpi, la bassa densità, impostato a 120 dpi;
- mdpi, 160 dpi, come detto è la baseline delle densità;
- tvdpi, pensata per le tv: solitamente impostata a 213 dpi;
- hdpi, densità alta: 240 dpi;
- xhdpi, densità ultra-alta: 320dpi.
Per comprendere meglio quanto detto, può essere utile considerare la relazione tra pixel e dp, che può essere sintetizzata matematicamente come segue:
px = dp*(dpi/160)
Ciò può essere letto affermando che il rapporto tra pixel e dp è pari a quello tra la densità del display ed il livello di parità 160 dpi.
Non è un caso quindi che, tra le risorse di default inserite nei progetti di Eclipse e Android Studio, l'immagine del logo del robottino verde (denominata ic_launcher.png) sia replicata in più cartelle drawable, ogni volta con dimensioni
differenti:
- in drawable-mdpi, misura 48X48 pixel;
- in drawable-hdpi, 72X72 pixel;
- in drawable-xhdpi, 96X96 pixel.
Più è alta la densità di pixel cui è destinata l'immagine, più grandi sono le sue dimensioni. Ciò per contrastare il naturale rimpicciolimento che provocherebbe un maggior numero di pixel, a parità di dimensioni. Tutto ciò avviene nel rispetto
delle proporzioni dettate dalla formula descritta poc'anzi.
Best practises
Affinchè le nostre applicazioni possano avere una migliore diffusione su dispositivi eterogenei, è fondamentale dotarle di interfacce fluide,
e per questo è bene tenere a mente alcuni consigli:
- utilizzare il più possibile i RelativeLayout, che ha per sua natura si adatta ai display;
- nel dimensionamento di View e Layout, evitare di dichiarare esplicitamente le misure facendo ricorso il più possibile ai valori wrap_content e match_parent;
- tutte le misure necessarie vanno indicate in dp (o in sp per i font) evitando qualsiasi altra unità di misura che abbia attinenza col
mondo reale (pixel, millimetri, pollici, etc...); - diversificare le risorse in base alle possibili configurazioni dei dispositivi, predisponendo i nomi delle cartelle caratterizzati dagli
appositi modificatori. Ciò vale per le densità, con le directory drawable-ldpi, drawable-hdpi, eccetera, ma anche per le diverse modalità di orientamento del display (layout-land per landscape o
layout-port per portrait) e per le dimensioni del display (layout-small per schermi non superiori ai 3 pollici, ad esempio). La serie completa dei
modificatori è disponibile sulla documentazione ufficiale.