Assurer la compatibilité avec différentes densités de pixels

Non seulement les appareils Android ont des tailles d'écran différentes : téléphones, tablettes, téléviseurs, mais aussi des écrans avec des tailles de pixels différentes. Un un appareil peut avoir une taille de 160 pixels par pouce, tandis qu'un autre appareil peut en tenir à 480 de pixels dans le même espace. Si vous ne considérez pas ces variantes dans de pixels, le système peut s'adapter ce qui peut entraîner des images floues. s'affichent dans la mauvaise taille.

Cette page vous explique comment concevoir votre application différentes densités de pixels à l'aide d'unités de mesure indépendantes de la résolution et fournir d'autres ressources bitmap pour chaque densité de pixels.

Pour en savoir plus sur ces techniques, regardez la vidéo ci-dessous.

Pour en savoir plus sur la conception d'éléments d'icône, consultez les consignes relatives aux icônes Material Design.

Utiliser des pixels indépendants de la densité

Évitez d'utiliser des pixels pour définir des distances ou des tailles. Définir des dimensions avec les pixels posent problème, car les différents écrans ont des densités de pixels différentes, Ainsi, le même nombre de pixels correspond à différentes tailles physiques sur différents appareils.

<ph type="x-smartling-placeholder">
</ph> Image montrant deux exemples d&#39;écrans d&#39;appareils de différentes densités <ph type="x-smartling-placeholder">
</ph> Figure 1: Deux écrans de même taille peuvent avoir un nombre de pixels différent.

Conserver la taille visible de votre interface utilisateur sur les écrans de différentes densités, concevez votre UI pixels indépendants de la densité (dp) comme unité de mesure. Un dp correspond à unité de pixel virtuel, à peu près égale à un pixel sur un écran de densité moyenne (160 ppp, ou densité de référence). Android traduit cette valeur en le nombre approprié de pixels réels pour chaque densité.

Prenons l'exemple des deux appareils de la figure 1. Une vue qui est une largeur de 100 pixels semble beaucoup plus grande sur l'appareil, à gauche. Une vue dont la largeur est de 100 dp apparaît comme la même taille sur les deux écrans.

Lorsque vous définissez des tailles de texte, vous pouvez utiliser des paramètres évolutifs pixels (sp) comme unités. L'unité de SP est Elle est identique à une taille dp, mais elle est redimensionnée selon les préférences de l'utilisateur. la taille du texte. N'utilisez jamais sp pour les tailles de mise en page.

Par exemple, pour spécifier l'espacement entre deux vues, utilisez dp:

<Button android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/clickme"
    android:layout_marginTop="20dp" />

Lorsque vous spécifiez la taille du texte, utilisez sp:

<TextView android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="20sp" />

Convertir les unités de dp en pixels

Dans certains cas, vous devez exprimer les dimensions en dp, puis les convertir en pixels. Conversion d'unités dp en pixels d'écran se présente comme suit:

px = dp * (dpi / 160)

Remarque:Ne codez jamais cette équation en dur pour calculer le nombre de pixels. Utilisez plutôt TypedValue.applyDimension(), qui convertit de nombreux types de dimensions (dp, sp, etc.) en pixels.

Imaginez une application dans laquelle un geste de défilement ou de glissement d'un geste vif est reconnu. après un déplacement d'au moins 16 pixels du doigt de l'utilisateur. Sur une base de référence écran, le doigt de l'utilisateur doit déplacer 16 pixels / 160 dpi, soit 2,5 mm (soit 1/10 de pouce), avant le geste est reconnu.

Sur un appareil Avec un écran haute densité (240 ppp), le doigt de l'utilisateur doit se déplacer 16 pixels / 240 dpi, qui égal à 1,7 mm. La distance est beaucoup plus courte et l'application semble donc plus sensible aux yeux de l'utilisateur.

Pour résoudre ce problème, exprimez le seuil de geste dans le code en dp et puis le convertir en pixels. Exemple :

Kotlin

// The gesture threshold expressed in dp
private const val GESTURE_THRESHOLD_DP = 16.0f

private var gestureThreshold: Int = 0

// Convert the dps to pixels, based on density scale
gestureThreshold = TypedValue.applyDimension(
  COMPLEX_UNIT_DIP,
  GESTURE_THRESHOLD_DP + 0.5f,
  resources.displayMetrics).toInt()

// Use gestureThreshold as a distance in pixels...

Java

// The gesture threshold expressed in dp
private final float GESTURE_THRESHOLD_DP = 16.0f;

// Convert the dps to pixels, based on density scale
int gestureThreshold = (int) TypedValue.applyDimension(
  COMPLEX_UNIT_DIP,
  GESTURE_THRESHOLD_DP + 0.5f,
  getResources().getDisplayMetrics());

// Use gestureThreshold as a distance in pixels...

Le champ DisplayMetrics.density spécifie le facteur de scaling utilisé pour convertir les unités de dp en en fonction de la densité actuelle en pixels. Sur un écran de densité moyenne, DisplayMetrics.density est égal(e) à 1,0, contre 1,5 sur un écran haute densité. Sur un écran extra-haute densité, 2,0 sur un écran à faible densité, 0,75. Ce chiffre est utilisé par TypedValue.applyDimension() pour obtenir le nombre réel de pixels pour l'écran actuel.

Utiliser des valeurs de configuration pré-adaptées

Vous pouvez utiliser la classe ViewConfiguration pour accéder aux les distances, les vitesses et les temps utilisés par le système Android. Par exemple, le paramètre distance en pixels utilisés par le framework afin d'obtenir le seuil de défilement avec getScaledTouchSlop():

Kotlin

private val GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).scaledTouchSlop

Java

private final int GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).getScaledTouchSlop();

Méthodes dans ViewConfiguration commençant par le préfixe getScaled sont assurés de renvoyer une valeur en pixels qui s'affiche correctement, quelle que soit comme la densité de pixels.

Préférer des graphiques vectoriels

Au lieu de créer plusieurs versions spécifiques à la densité d'une image, vous pouvez créer un seul graphique vectoriel. Les graphiques vectoriels créent une image à l'aide de XML pour définir des chemins et des couleurs, au lieu d'utiliser des bitmaps de pixels. Ainsi, les vecteurs les images peuvent s'adapter à n'importe quelle taille sans mettre à l'échelle les artefacts, bien qu'ils soient généralement mieux pour les illustrations comme les icônes, pas pour les photographies.

Les graphiques vectoriels sont souvent fournis sous forme de fichiers SVG (Scalable Vector Graphics), mais Android n'étant pas compatible avec ce format, vous devez convertir les fichiers SVG en Le vecteur d'Android drawable.

Vous pouvez convertir un SVG en drawable vectoriel à l'aide de l'outil Vector Asset Studio comme suit:

  1. Dans la fenêtre Project (Projet), effectuez un clic droit sur le répertoire res, puis sélectionnez Nouveau > Élément vectoriel.
  2. Sélectionnez Fichier local (SVG, PSD).
  3. Localisez le fichier que vous souhaitez importer et apportez les modifications nécessaires.

    <ph type="x-smartling-placeholder">
    </ph> Image montrant comment importer des fichiers SVG dans Android Studio <ph type="x-smartling-placeholder">
    </ph> Figure 2: importation d'un fichier SVG avec Android Studio

    Vous remarquerez peut-être des erreurs dans la fenêtre Asset Studio ce qui indique que les drawables vectoriels ne sont pas compatibles avec certaines propriétés du fichier. Cela ne vous empêche pas d'importer le fichier. les propriétés non compatibles sont ignorés.

  4. Cliquez sur Suivant.

  5. Sur l'écran suivant, confirmez l'ensemble de sources dans lequel vous souhaitez ajouter le fichier dans votre projet. et cliquez sur Terminer.

    Étant donné qu'un drawable vectoriel peut être utilisé avec toutes les densités de pixels, ce fichier se trouve dans votre répertoire drawable par défaut, comme illustré la hiérarchie. Vous n'avez pas besoin d'utiliser des répertoires spécifiques à la densité.

    res/
      drawable/
        ic_android_launcher.xml
    

Pour en savoir plus sur la création de graphiques vectoriels, consultez la documentation sur le drawable vectoriel. dans la documentation Google Cloud.

Fournir d'autres bitmaps

Pour offrir une qualité graphique de qualité sur les appareils de différentes densités de pixels, fournir plusieurs versions de chaque bitmap dans votre application, une pour chaque un bucket de densité, à une résolution correspondante. Sinon, Android doit évoluer votre bitmap afin qu'il occupe le même espace visible sur chaque écran, ce qui de mise à l'échelle des artefacts tels que le floutage.

<ph type="x-smartling-placeholder">
</ph> Image montrant les tailles relatives de bitmaps à différentes densités <ph type="x-smartling-placeholder">
</ph> Figure 3: Tailles relatives des bitmaps dans différents segments de densité

Plusieurs segments de densité peuvent être utilisés dans vos applications. Table 1 décrit les différents qualificatifs de configuration disponibles et les types d'écrans auxquelles ils s'appliquent.

Tableau 1. Des qualificatifs de configuration pour différentes en pixels.

Qualificatif de densité Description
ldpi Ressources pour les écrans basse densité (ldpi) (environ 120 ppp).
mdpi Ressources pour les écrans de densité moyenne (mdpi) (~160 ppp). Il s'agit de la référence de la densité.
hdpi Ressources pour les écrans haute densité (hdpi) (environ 240 ppp).
xhdpi Ressources pour les écrans extra-haute densité (xhdpi) (environ 320 ppp).
xxhdpi Ressources pour les écrans extra-extra-haute densité (xxhdpi) (environ 480 ppp).
xxxhdpi Ressources destinées aux utilisations extra-extra-extra-haute densité (xxxhdpi) (environ 640 ppp).
nodpi Ressources pour toutes les densités. Ces ressources sont indépendantes de la densité. Le système ne adapte les ressources associées à ce qualificatif, quelle que soit la densité de l'écran actuel.
tvdpi Ressources pour les écrans compris entre mdpi et hdpi approximativement ~213 PPP. Il n'est pas considéré comme un groupe de densité "principal". Il est principalement destiné pour les téléviseurs, et la plupart des applications n'en ont pas besoin. Les formats mdpi et hdpi sont fournis de ressources suffisantes pour la plupart des applications, approprié. S'il est nécessaire de fournir des ressources tvdpi, leur taille à un facteur de 1,33 * mdpi. Par exemple, une image de 100 x 100 pixels pour les écrans mdpi font 133 x 133 pixels pour tvdpi.

Pour créer d'autres drawables bitmap pour différentes densités, suivez les un ratio de mise à l'échelle de 3:4:6:8:12:16 entre les six densités principales. Par exemple, si vous avez Un drawable bitmap de 48 x 48 pixels pour les écrans de densité moyenne, les tailles sont les suivantes:

  • 36 x 36 (x 0,75) pour une faible densité (ldpi)
  • 48 x 48 (1 fois la référence) pour la densité moyenne (mdpi)
  • 72 x 72 (1,5 x) pour la haute densité (hdpi)
  • 96 x 96 (x 2,0 pour extra-haute densité) (xhdpi)
  • 144 x 144 (3,0x) pour extra-extra-haute densité (xxhdpi)
  • 192 x 192 (x4) pour une densité extra-extra-extra-haute densité (xxxhdpi)

Placez les fichiers image générés dans le sous-répertoire approprié. sous res/:

res/
  drawable-xxxhdpi/
    awesome_image.png
  drawable-xxhdpi/
    awesome_image.png
  drawable-xhdpi/
    awesome_image.png
  drawable-hdpi/
    awesome_image.png
  drawable-mdpi/
    awesome_image.png

Ensuite, chaque fois que vous faites référence à @drawable/awesomeimage, le système sélectionne le bitmap approprié en fonction de la résolution de l'écran. Si vous ne fournit pas de ressource spécifique à la densité pour cette densité, le système la correspondance qui suit et l'adapte à l'écran.

Conseil:Si vous disposez de ressources drawables que le système ne doit pas faire évoluer, par exemple vous pouvez apporter certains ajustements à l'image lors de l'exécution, placez-les avec le qualificatif de configuration nodpi. Les ressources associées à ce qualificatif sont considérées comme étant indépendantes de la densité. le système ne les met pas à l'échelle.

Pour en savoir plus sur les autres qualificatifs de configuration et comment Android sélectionne les ressources appropriées pour la configuration actuelle de l'écran, consultez la présentation des ressources de l'application.

Placer les icônes d'application dans les répertoires mipmap

Comme pour les autres éléments bitmap, vous devez fournir des versions spécifiques à la densité l'icône de votre application. Cependant, certains lanceurs d'applications affichent l'icône d'application jusqu'à 25% plus grande que celle appelée par le bucket de densité de l'appareil.

Par exemple, si le segment de densité d'un appareil est de xxhdpi et que l'icône d'application la plus grande fournir est dans drawable-xxhdpi, le lanceur d'applications redimensionne cette icône ce qui le rend moins net.

Pour éviter cela, les icônes de votre application dans les répertoires mipmap au lieu des répertoires drawable. Retirer le "J’aime" drawable répertoires, tous les répertoires mipmap sont conservés dans l'APK, même si vous créez des APK spécifiques à la densité. Cela permet aux lanceurs d'applications de choisir le meilleur icône de résolution à afficher sur l'écran d'accueil.

res/
  mipmap-xxxhdpi/
    launcher_icon.png
  mipmap-xxhdpi/
    launcher_icon.png
  mipmap-xhdpi/
    launcher_icon.png
  mipmap-hdpi/
    launcher_icon.png
  mipmap-mdpi/
    launcher_icon.png

Dans l'exemple précédent d'un appareil xxhdpi, vous pouvez fournir un icône de lanceur de densité plus élevée dans le répertoire mipmap-xxxhdpi.

Pour obtenir des consignes de conception des icônes, consultez la page Icônes système.

Pour savoir comment créer des icônes d'application, consultez Créer des icônes d'application avec Image Asset Studio.

Conseils pour les problèmes de densité inhabituels

Cette section décrit comment Android effectue le scaling des bitmaps sur différentes densités de pixels et comment mieux contrôler les bitmaps sont dessinés sur différentes densités. À moins que votre application manipule les éléments graphiques ou si vous avez rencontré des problèmes lors de l'exécution avec différentes densités de pixels, vous vous pouvez ignorer cette section.

Pour mieux comprendre comment accepter plusieurs densités lorsque vous manipulez des éléments graphiques vous devez savoir comment le système garantit l'échelle appropriée pour les bitmaps. Pour ce faire, procédez comme suit:

  1. Pré-scaling des ressources, telles que des drawables bitmap

    En fonction de la densité de l'écran actuel, le système utilise de votre application. Si les ressources ne sont pas disponibles avec la bonne densité, le système charge les ressources par défaut et les redimensionne selon les besoins. Le système suppose que les ressources par défaut (celles d'une sans qualificatifs de configuration) sont conçus pour la version de référence (mdpi) et redimensionne ces bitmaps à la taille appropriée la densité actuelle en pixels.

    Si vous demandez les dimensions d'une ressource pré-évoluée, le système renvoie des valeurs représentant les dimensions après l'ajustement. Par exemple, un bitmap conçu sur 50 x 50 pixels pour un écran mdpi est mis à l'échelle à 75 x 75 pixels sur un écran hdpi (s'il n'y a pas d'autre ressource pour hdpi), et le système signale la taille en tant que telle.

    Dans certains cas, vous ne souhaiterez peut-être pas qu'Android effectue le pré-scaling une ressource. Le moyen le plus simple d'éviter le pré-scaling consiste à placer la ressource dans un répertoire de ressources avec le qualificatif de configuration nodpi. Exemple :

    res/drawable-nodpi/icon.png

    Lorsque le système utilise le bitmap icon.png de ce dossier, il ne le met pas à l'échelle. en fonction de la densité actuelle de l'appareil.

  2. Autoscaling des dimensions et des coordonnées en pixels

    Vous pouvez désactiver les dimensions et les images pré-redimensionnables en définissant android:anyDensity. sur "false" dans le fichier manifeste, ou de manière programmatique pour un Bitmap en définissant inScaled sur "false". Dans Dans ce cas, le système ajuste automatiquement les coordonnées en pixels absolues les valeurs de dimension au moment du dessin. Cela permet de s'assurer que les valeurs les éléments à l'écran restent affichés à peu près à la même taille physique pour qu'elles puissent s'afficher avec la densité de pixels de référence (mdpi). Le système gère de façon transparente pour l'application, et indique le nombre de pixels mis à l'échelle à l'application, plutôt que ses dimensions physiques en pixels.

    Par exemple, supposons qu'un appareil dispose d'un écran haute densité WVGA, de 480 x 800, à peu près de la même taille qu'un écran HVGA traditionnel, mais il exécute une application qui a désactivé avant la mise à l'échelle. Dans ce cas, le système "ment" à l'application lorsqu'elle demande l'écran et rapporte 320 x 533, soit la traduction mdpi approximative de la densité en pixels.

    Ensuite, quand L'application effectue des opérations de dessin, par exemple pour invalider un rectangle de (10,10) à (100, 100), le système transforme les coordonnées en les redimensionnant à l'échelle appropriée. invalide la région (15,15) en (150, 150). Cet écart peut entraîner un comportement inattendu votre application manipule directement le bitmap mis à l'échelle, mais cela est considéré comme afin d'optimiser les performances de votre application. Si vous rencontrez ce consultez la section Convertir des unités dp en pixels unités de mesure.

    En règle générale, vous ne désactivez pas le pré-scaling. Le meilleur moyen de prendre en charge écrans, vous devez suivre les techniques de base décrites sur cette page.

Si votre application manipule des bitmaps ou interagit directement avec les pixels à l'écran d'une autre manière, vous devrez peut-être prendre des mesures supplémentaires pour prendre en charge différentes en pixels. Par exemple, si vous répondez aux gestes tactiles en comptant les de pixels qu'un doigt croise, vous devez utiliser des valeurs de pixels indépendantes de la densité plutôt que des pixels réels, mais vous pouvez convertir des valeurs dp en px.

Tester sur toutes les densités de pixels

Tester votre application sur plusieurs appareils avec différents pixels afin que votre interface utilisateur s'adapte correctement. Les tests sur un appareil lorsque cela est possible ; utilisez l'application mobile Android à l'émulateur si vous n'avez pas accès pour les différentes densités de pixels.

Si vous souhaitez effectuer des tests sur des appareils physiques, mais si vous ne souhaitez pas acheter ces appareils, vous pouvez utiliser Firebase Test Lab pour accéder aux appareils d'un centre de données Google.