Os dispositivos Android não têm apenas tamanhos de tela diferentes, como celulares, tablets, TVs, etc., mas também têm telas com diferentes tamanhos de pixel. Um dispositivo pode ter 160 pixels por polegada, enquanto outro dispositivo cabe 480 pixels no mesmo espaço. Se você não considerar essas variações densidade de pixel, o sistema pode dimensionar suas imagens, resultando em imagens borradas, ou as imagens podem aparecem no tamanho errado.
Esta página mostra como você pode projetar seu aplicativo para oferecer suporte densidades de pixel diferentes usando unidades de medidas independentes de resolução e fornecer recursos de bitmap alternativos para cada densidade de pixel.
Assista ao vídeo a seguir para ter uma visão geral dessas técnicas.
Para saber mais sobre o design de recursos de ícones, consulte as Diretrizes de ícones do Material Design (em inglês).
Usar pixels de densidade independente
Evite usar pixels para definir distâncias ou tamanhos. Definir dimensões com pixels é um problema porque telas diferentes têm densidades de pixel diferentes, de modo que o mesmo número de pixels corresponde a diferentes tamanhos físicos em dispositivos diferentes.
![Uma imagem mostrando dois exemplos de telas de dispositivos com densidades diferentes](https://developer.android.com/static/images/screens_support/densities-phone_2x.png?authuser=9&hl=pt)
Para preservar o tamanho visível da interface em telas com diferentes densidades, projete sua interface usando pixels de densidade independente (dp) como unidade de medida. Um dp é um unidade virtual de pixel que é aproximadamente igual a um pixel em uma tela de densidade média (160 dpi, a densidade "básica"). O Android converte esse valor para o número apropriado de pixels reais para cada densidade.
Considere os dois dispositivos da Figura 1. Uma visualização que é 100 pixels de largura parece muito maior no dispositivo à esquerda. Uma visualização definido como 100 dp de largura, tem o mesmo tamanho nas duas telas.
Ao definir tamanhos de texto, você pode usar ferramentas escalonáveis pixels (sp) como unidades. A unidade sp é é do mesmo tamanho de um dp, por padrão, mas é redimensionado com base na preferência do usuário tamanho do texto. Nunca use sp para tamanhos de layout.
Por exemplo, para especificar o espaçamento entre duas visualizações, use dp:
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/clickme" android:layout_marginTop="20dp" />
Ao especificar o tamanho do texto, use sp:
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20sp" />
Converter unidades de dp em unidades de pixel
Em alguns casos, você precisa expressar dimensões em dp e depois convertê-los em pixels. Conversão de unidades dp em pixels da tela é o seguinte:
px = dp * (dpi / 160)
Observação:nunca codifique essa equação para calcular pixels. Em vez disso, use
TypedValue.applyDimension()
,
que converte vários tipos de dimensões (dp, sp etc.) em pixels.
Imagine um app em que um gesto de rolagem ou de deslize rápido é reconhecido
depois que o dedo do usuário tiver movido pelo menos 16 pixels. Com base na linha de base
na tela, o dedo do usuário precisa se mover 16 pixels
/ 160 dpi
, o que equivale a 2,5 mm (1/10 de polegada), antes de
o gesto for reconhecido.
Em um dispositivo
Em uma tela de alta densidade (240 dpi), o dedo do usuário precisa se mover
16 pixels / 240 dpi
, que
igual a 1,7 mm (1/15 de polegada). A distância é muito mais curta, e
o aplicativo, portanto, parece mais sensível para o usuário.
Para corrigir esse problema, expresse o limite de gestos no código em dp e e depois converter em pixels reais. Exemplo:
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...
O campo DisplayMetrics.density
especifica o fator de escala usado para converter unidades dp em
de acordo com a densidade de pixels atual. Em uma tela de densidade média,
DisplayMetrics.density
é igual a
1,0 e em uma tela de alta densidade é igual a 1,5. Em uma tela de densidade extra-alta,
ela equivale a 2,0 e, em uma tela de baixa densidade, igual a 0,75. Esse número é
usado por TypedValue.applyDimension()
para
para consultar a contagem real de pixels da tela atual.
Usar valores de configuração pré-dimensionados
É possível usar a classe ViewConfiguration
para acessar recursos
distâncias, velocidades e tempos usados pelo sistema Android. Por exemplo, o
distância em pixels usada pelo framework, porque o limite de rolagem pode ser obtido
com getScaledTouchSlop()
:
Kotlin
private val GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).scaledTouchSlop
Java
private final int GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).getScaledTouchSlop();
Métodos em ViewConfiguration
que começam com o prefixo getScaled
têm a garantia de retornar um valor em pixels exibido corretamente, independentemente da
densidade de pixels.
Dar preferência a gráficos vetoriais
Uma alternativa à criação de diversas versões de densidade específica de uma imagem é criar apenas um gráfico vetorial. Gráficos vetoriais criam uma imagem usando XML para define caminhos e cores em vez de usar bitmaps de pixels. Assim, o vetor gráficos podem ser dimensionados para qualquer tamanho sem artefatos de dimensionamento, embora sejam normalmente melhor para ilustrações como ícones, não para fotografias.
Gráficos vetoriais costumam ser fornecidos como arquivos SVG (Scalable Vector Graphics), mas o Android não oferece suporte a esse formato, por isso você deve converter os arquivos SVG Vetor do Android drawable.
É possível converter um SVG em um drawable vetorial usando o Vector Asset Studio da seguinte forma:
- Na janela Project, clique com o botão direito do mouse no diretório res e selecione Novo > Vector Asset.
- Selecione Local file (SVG, PSD).
Localize o arquivo que você quer importar e faça os ajustes necessários.
Figura 2: importar um SVG com o Android Studio Talvez você encontre alguns erros na janela do Asset Studio. indicando que drawables vetoriais não oferecem suporte a algumas propriedades do arquivo. Isso não impede que você importe o arquivo; as propriedades sem suporte são ignorados.
Clique em Next.
Na próxima tela, confirme o conjunto de origem em que você quer colocar o arquivo no projeto e clique em Concluir.
Como um drawable vetorial pode ser usado em todas as densidades de pixel, esse arquivo entra no seu diretório de drawables padrão, como mostrado no exemplo a seguir. hierarquia. Você não precisa usar diretórios específicos de densidade.
res/ drawable/ ic_android_launcher.xml
Para mais informações sobre como criar gráficos vetoriais, leia drawable vetorial na documentação do Google Cloud.
Fornecer bitmaps alternativos
Para oferecer uma boa qualidade gráfica em dispositivos com densidades de pixel diferentes, fornecer várias versões de cada bitmap em seu app, uma para cada em um bucket de densidade específica, em uma resolução correspondente. Caso contrário, o Android precisa ser escalonado seu bitmap para que ele ocupe o mesmo espaço visível em cada tela, resultando em Artefatos de dimensionamento, como desfoque.
![Uma imagem que mostra tamanhos relativos para bitmaps em diferentes densidades](https://developer.android.com/static/images/screens_support/devices-density_2x.png?authuser=9&hl=pt)
Há vários intervalos de densidade disponíveis para uso nos seus apps. Tabela 1 descreve os diferentes qualificadores de configuração disponíveis e quais tipos de tela a que se aplicam.
Tabela 1. Qualificadores de configuração para diferentes densidades de pixels ideais.
Qualificador de densidade | Descrição |
---|---|
ldpi |
Recursos para telas de baixa densidade (ldpi) (cerca de 120 dpi). |
mdpi |
Recursos para telas de média densidade (mdpi) (cerca de 160 dpi). Essa é a linha de base densidade |
hdpi |
Recursos para telas de alta densidade (hdpi) (cerca de 240 dpi). |
xhdpi |
Recursos para telas de densidade extra-alta (xhdpi) (cerca de 320 dpi). |
xxhdpi |
Recursos para telas de densidade extra-extra-alta (xxhdpi) (cerca de 480 dpi). |
xxxhdpi |
Recursos para telas de densidade extra-extra-extra-alta (xxxhdpi) (cerca de 640 dpi). |
nodpi |
Recursos para todas as densidades. Esses são recursos independentes de densidade. O sistema não dimensionar recursos marcados com esse qualificador, independentemente da densidade da tela atual. |
tvdpi |
recursos para telas entre mdpi e hdpi; aproximadamente
aproximadamente 213 dpi. Não é considerado um grupo de densidade "principal".' Ele é destinado principalmente
para televisões, e a maioria dos apps não precisa deles, fornecendo mdpi e hdpi.
recursos é suficiente para a maioria dos aplicativos, e o sistema os escalona conforme
apropriados. Se você achar necessário fornecer recursos tvdpi ,
dimensione-os a um fator de 1,33 * mdpi. Por exemplo, uma imagem de 100 x 100 pixels para
mdpi é 133 x 133 pixels para tvdpi. |
Para criar drawables bitmap alternativos para diferentes densidades, siga as 3:4:6:8:12:16 entre as seis densidades principais. Por exemplo, se você tiver um drawable de bitmap de 48 x 48 pixels para telas de densidade média, os tamanhos serão:
- 36 x 36 (0,75 x) para densidade baixa (ldpi)
- 48 x 48 (1,0 x - configuração básica) para densidade média (mdpi)
- 72 x 72 (1,5 x) para alta densidade (hdpi)
- 96 x 96 (2,0 x) para densidade extra-alta (xhdpi)
- 144 x 144 (3,0 x) para densidade extra-extra-alta (xxhdpi)
- 192 x 192 (4,0 x) para densidade extra-extra-extra-alta (xxxhdpi)
Colocar os arquivos de imagem gerados no subdiretório adequado
em 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
Assim, sempre que você fizer referência a @drawable/awesomeimage
,
o sistema selecionará o bitmap apropriado com base no dpi da tela. Se você
não fornecerem um recurso específico de densidade, o sistema localizará
a próxima melhor correspondência e a dimensiona para caber na tela.
Dica:se você tiver recursos drawable
que você não quer que o sistema escalone, por exemplo, ao realizar
fazer alguns ajustes na imagem durante a execução, colocá-los em um
com o qualificador de configuração nodpi
.
Recursos com esse qualificador são considerados agnósticos de densidade, e
o sistema não os dimensiona.
Para mais informações sobre outros qualificadores de configuração e como o Android seleciona os recursos adequados para a configuração da tela atual, consulte a Visão geral dos recursos de app.
Colocar ícones de app em diretórios mipmap
Assim como acontece com outros recursos de bitmap, você precisa fornecer versões específicas para densidades de ícone do seu app. No entanto, alguns inicializadores de apps exibem o ícone do app em até 25% maior do que o exigido pelo intervalo de densidade do dispositivo.
Por exemplo, se o intervalo de densidade de um dispositivo for xxhdpi e o maior ícone de app que você
fornecer esteja em drawable-xxhdpi
, o Acesso rápido aos apps dimensionará esse ícone,
o que faz com que pareça menos nítido.
Para evitar isso, coloque todos
os ícones do app nos diretórios mipmap
em vez de drawable
. Não gostei
Diretórios drawable
, todos os diretórios mipmap
serão mantidos no APK, mesmo
se você criar APKs específicos para densidades. Assim, os apps de tela de início
escolhem as melhores
ícone de resolução a ser exibido na tela inicial.
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
No exemplo anterior de um dispositivo xxhdpi, é possível fornecer uma
ícone de maior densidade na tela de início no diretório mipmap-xxxhdpi
.
Para orientações sobre criação de ícones, consulte Ícones do sistema.
Se precisar de ajuda para criar ícones, consulte Criar ícones com o Image Asset Studio.
Orientações para problemas de densidade incomuns
Esta seção descreve como o Android realiza o escalonamento para bitmaps em diferentes densidades de pixel e como é possível ter mais controle bitmaps são desenhados em diferentes densidades. A menos que seu aplicativo manipule gráficos ou tiver encontrado problemas ao executar em densidades de pixel diferentes, ignore esta seção.
Para entender melhor como oferecer suporte a várias densidades ao manipular gráficos no ambiente de execução, você precisa saber como o sistema ajuda a garantir o escalonamento adequado para bitmaps. Isso é feito das seguintes maneiras:
- Pré-dimensionamento de recursos, como drawables de bitmap
Com base na densidade da tela atual, o sistema usa qualquer densidade específica recursos do seu app. Se os recursos não estiverem disponíveis a densidade correta, o sistema carrega os recursos padrão e os aumenta ou diminui conforme necessário. O sistema assume que os recursos padrão (aqueles de uma sem qualificadores de configuração) são projetados para o valor de referência densidade de pixel (mdpi) e redimensiona esses bitmaps para o tamanho apropriado para a densidade de pixels atual.
Se você solicitar as dimensões de um recurso pré-dimensionado, o sistema retornará valores que representa as dimensões após o redimensionamento. Por exemplo, um bitmap projetado para 50 x 50 pixels para uma tela mdpi é dimensionada para 75 x 75 pixels em uma tela hdpi (se não houver um recurso alternativo) para hdpi). O sistema informa o tamanho dessa forma.
Existem algumas situações em que você pode não querer que o Android pré-dimensione de um recurso. A maneira mais fácil de evitar o pré-escalonamento é colocar o recurso em um diretório de recursos com o qualificador de configuração
nodpi
. Exemplo:res/drawable-nodpi/icon.png
Quando o sistema usa o bitmap
icon.png
dessa pasta, ele não o dimensiona com base na densidade atual do dispositivo. - Escalonamento automático de dimensões e coordenadas em pixels
Para desativar as dimensões e imagens de pré-dimensionamento, defina
android:anyDensity
como"false"
no manifesto ou de forma programática para umBitmap
definindoinScaled
como"false"
. Em neste caso, o sistema automaticamente dimensiona todas as coordenadas absolutas de pixel e valores de dimensão no momento do desenho. Isso garante que os pixels definidos os elementos da tela ainda são exibidos com aproximadamente o mesmo tamanho físico para que eles possam ser exibidos com a densidade de pixel básica (mdpi). O sistema gerencia esse dimensionamento de forma transparente para o aplicativo e informa o pixel dimensionado dimensões de pixels ao aplicativo, em vez de dimensões físicas em pixels.Por exemplo, suponha que um dispositivo tenha uma tela WVGA de alta densidade, de 480 x 800 mesmo tamanho que uma tela HVGA tradicional, mas está executando um aplicativo desativado pré-escalonamento. Nesse caso, o sistema "mentira" para o app quando ele consultar dimensões e relatórios de 320 x 533, a conversão aproximada em mdpi para a densidade de pixels.
Então, quando o aplicativo realiza operações de desenho, como invalidar um retângulo de (10,10) a (100, 100), o sistema transforma as coordenadas dimensionando-as para o valor adequado e, invalida a região (15,15) para (150, 150). Essa discrepância pode causar um comportamento inesperado se seu app manipula diretamente o bitmap dimensionado, mas isso é considerado uma para garantir o melhor desempenho possível do app. Se você encontrar esse situação, leia Converter unidades dp em pixel de unidade de medida.
Normalmente, você não desativa o pré-dimensionamento. A melhor maneira de dar suporte a vários é seguir as técnicas básicas descritas nesta página.
Se o app manipular bitmaps ou interagir diretamente com pixels na tela de outra forma, pode ser necessário tomar medidas adicionais para dar suporte a diferentes densidades de pixels ideais. Por exemplo, se você responder a gestos de toque contando os número de pixels cruzados por um dedo, você precisa usar o método valores de pixel de densidade independente, em vez de pixels reais, mas você pode fazer a conversão entre valores dp e px.
Testar em todas as densidades de pixel
Testar seu app em vários dispositivos com pixels diferentes densidades diferentes para que você possa garantir que a interface seja dimensionada corretamente. O teste em um dispositivo físico dispositivo, quando possível. use a plataforma Emulador, se você não tiver acesso a recursos dispositivos para todas as densidades de pixel diferentes.
Se você quiser testar em dispositivos físicos, mas Se você não quiser comprar os dispositivos, poderá usar o Firebase Test Lab para acessar dispositivos em um data center do Google.