Qual é a diferença entre -anydpi e -nodpi?

108

Se você usar o assistente Vector Asset no Android Studio 1.5.0, qualquer XML drawable vetorial que você importar usando esse assistente entrará res/drawable/.

No entanto, o build/diretório e o APK resultante mostram que esses arquivos XML foram movidos para um res/drawable-anydpi-v21/diretório de recursos. A -v21parte faz sentido, pois VectorDrawablesó é compatível com API de nível 21+. No entanto, -anydpiparece não ter documentos. Eu esperava -nodpi, tanto para o destino de importação original quanto para onde o sistema de compilação decide movê-lo.

Alguém viu declarações oficiais sobre o que -anydpisignifica e com que relação -nodpi? Estou procurando efeitos práticos, não apenas o que alguns comentários de código sugerem.

CommonsWare
fonte

Respostas:

106

Nodpi

Esses são recursos independentes de densidade. O sistema não dimensiona recursos marcados com este qualificador, independentemente da densidade da tela atual.

Por exemplo:

  • drawable- nodpi /dot.png

O ponto aparecerá pequeno em xxhdpi e grande em ldpi.

No entanto, o resolvedor de recursos corresponderá a um qualificador específico, se houver.

Por exemplo

  • drawable- hdpi /eg.png
  • drawable- nodpi -v21 / eg.xml

Em um dispositivo hdpi Lollipop (API 21), o bitmap é usado.

Em um dispositivo xhdpi Lollipop (API 21), o vetor é usado.

Anydpi

Esses recursos têm precedência em qualquer dpi.

Por exemplo

  • drawable- hdpi /eg.png
  • drawable- anydpi -v21 / eg.xml

Em um dispositivo hdpi Lollipop (API 21), o vetor é usado.

Em um dispositivo xhdpi Lollipop (API 21), o vetor é usado.

Referência

Nota : anydpi foi adicionado na alteração Ic3288d0236fe0bff20bb1599aba2582c25b0db32 .

rds
fonte
Não é isso que estou vendo. Citando meu bounty: "Dadas duas edições do mesmo recurso em res / drawable-nodpi / e res-drawable-mdpi /, recebo res / drawable-nodpi / edition em um Nexus 5 executando Android 6.0, que é um -xxhdpi dispositivo". Você tem um projeto de exemplo que demonstra o comportamento que está citando?
CommonsWare
Isso é porque você usou drawable. O comportamento do SDK pode ter mudado. Consulte VectorDrawable: o Android carrega PNGs xhdpi em vez do recurso vetorial
rds
"Isso é porque você usou drawable" - você também usou em sua resposta. Cada diretório de recursos que você cita em sua resposta é um drawablediretório de recursos, assim como os dois diretórios que citei em meu bounty são drawablediretórios de recursos.
CommonsWare
"Em um xxxdpi, a estrutura pegará o bitmap hdpi." - isso é especificamente o que não está acontecendo, embora meu teste seja em um -xxhdpidispositivo. Eu tenho res/drawable-mdpi/nodpi_and_m.pnge res/drawable-nodpi/nodpi_and_m.xml. Em um -xxhdpidispositivo Nexus 5, o recurso usado é res/drawable-nodpi/nodpi_and_m.xml. De acordo com o seu algoritmo, e minhas expectativas, res/drawable-mdpi/nodpi_and_m.pngdeve ser usado. Não é isso que está acontecendo.
CommonsWare
2
Resumindo: você deve colocar vetores em drawable-anydpi-v21. Se você tiver a biblioteca support-vector-drawable, pode colocá-los drawable-anydpiou simplesmente drawable.
rds
17

O código-fonte contém os seguintes comentários (linha 639):

/**
 * Value for {@link #densityDpi} for resources that scale to any density (vector drawables).
 * {@hide}
 */
public static final int DENSITY_DPI_ANY = 0xfffe;

/**
 * Value for {@link #densityDpi} for resources that are not meant to be scaled.
 * {@hide}
 */
public static final int DENSITY_DPI_NONE = 0xffff;

Espero que isso esclareça a confusão.

Vishavjeet Singh
fonte
8
"Espero que isso esclareça a confusão" - não realmente. Não está claro qual é a diferença entre "dimensionar para qualquer densidade" e "não destinado a ser dimensionado" significa na prática. Os drawables em -nodpidiretórios certamente são dimensionados com base no tamanho, de acordo com as regras em vigor sobre como o drawable é usado.
CommonsWare
"Não foi feito para ser escalado" significa que eles não serão escalados, não importa o que o programador faça ou a densidade.
Vishavjeet Singh
Acho que eles querem dizer com a frase "dimensionar para qualquer densidade" que se referem a drawables vetoriais que serão redimensionados para se ajustar a qualquer densidade, não importa quão grande seja a densidade.
Vishavjeet Singh
3
foi adicionado a android.googlesource.com/platform/frameworks/base/+/31245b4%5E! , e com isso você pode aprender que provavelmente corrigiu algum bug 17007265
marcinj
1
@ MarcinJędrzejewski: Na verdade, o comentário "são escolhidos como a melhor combinação, a menos que haja uma configuração que corresponda exatamente à densidade solicitada" nesse commit me dá uma pista. Obrigado!
CommonsWare
10

nodpi: Recursos para todas as densidades. Esses são recursos independentes de densidade. O sistema não dimensiona recursos marcados com este qualificador, independentemente da densidade da tela atual.

anydpi: Este qualificador corresponde a todas as densidades de tela e tem precedência sobre outros qualificadores. Isso é útil para drawables vetoriais. Adicionado na API de nível 21.

dzikovskyy
fonte
9

Eu uso drawable-nodpi para tudo, incluindo muitos gráficos grandes para o meu jogo. Uma consequência não documentada da ampliação de seus gráficos é que isso aumenta o uso de memória exponencialmente. Portanto, se você tiver um gráfico de 1 MB no drawable, ele será dimensionado para 4 MB, 16 MB ou 64 MB, dependendo da resolução do dispositivo do usuário. E as resoluções dos dispositivos continuam aumentando. Essa ampliação não aumenta realmente a nitidez do gráfico, é claro. As ações de desenho podem direcionar o tamanho de cada gráfico em relação ao tamanho da tela de qualquer maneira, sem necessidade de inchar o aplicativo com várias pastas de desenho.

Androidcoder
fonte
3
resposta subestimada. Eu encontrei o mesmo problema: tinha uma imagem de 100 KB, mas frequentemente apresentava erros de OOM ao carregá-la. O aplicativo travou informando que não foi possível alocar 18 MB !!! Não conseguia entender como esses 100KB podiam ser transformados em 18 MB, mas na verdade era o resultado desse dimensionamento. Mudar a imagem para sem dpi resolveu o problema.
Simon Ninon