“-anydpi”和“-nodpi”的区别是什么?

128

如果您在Android Studio 1.5.0中使用矢量素材向导,那么您导入的任何矢量可绘制XML都将放置在res/drawable/目录下。

然而,build/目录和生成的APK显示,这些XML文件会被移动到res/drawable-anydpi-v21/资源目录中。-v21部分是有意义的,因为VectorDrawable仅受API Level 21+支持。但是,-anydpi似乎没有文档说明。我本来期望使用-nodpi,既用于原始导入目标,也用于构建系统选择移动的位置。

是否有人看到了关于-anydpi的官方声明,并且了解它与-nodpi的关系?我正在寻找实际效果,而不仅仅是一些代码注释所暗示的内容。


5
请阅读原帖作者的摘要。 - Suragch
现在是2023年,过去6年里我一直回到这个问题,因为我死活记不住哪个是哪个。我只知道其中一个是回退,另一个是覆盖。有人有助记符来帮助记忆吗? - Subaru Tashiro
4个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
134

nodpi

这些是密度无关资源。系统不会根据当前屏幕密度对标记有此限定符的资源进行缩放。

例如:

  • drawable-nodpi/dot.png

点在xxhdpi上将显得很小,在ldpi上则很大。

但是,如果存在特定的限定符,则资源解析器将匹配该限定符。

例如

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

在Lollipop (API 21) hdpi设备上使用位图。

在Lollipop (API 21) xhdpi设备上,使用矢量图。

anydpi

这些资源在任何dpi下优先。

例如

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

在Lollipop (API 21) hdpi设备上使用矢量图。

在Lollipop (API 21) xhdpi设备上,使用矢量图。

参考资料

注意:anydpi在change Ic3288d0236fe0bff20bb1599aba2582c25b0db32中添加。


1
这不是我看到的。引用我的悬赏要求:“在res/drawable-nodpi/和res-drawable-mdpi/中给定了相同资源的两个版本,但在运行Android 6.0的Nexus 5上,我得到的是res/drawable-nodpi/版本,这是一个-xxhdpi设备。”你有一个可以演示你所引用的行为的样例项目吗? - CommonsWare
这是因为您使用了drawable。SDK的行为可能已经发生了变化。请参见VectorDrawable:Android加载xhdpi PNG而不是矢量资源 - rds
1
在xxxdpi的情况下,框架将使用hdpi位图。尽管我的测试是在一个-xxhdpi设备上进行的,但实际情况并非如此。我有'drawable-mdpi / nodpi_and_m.png'和'drawable-nodpi / nodpi_and_m.xml'文件。在Nexus 5上,-xxhdpi设备上,使用的资源是'drawable-nodpi / nodpi_and_m.xml'。根据您的算法和我的期望,应该使用'drawable-mdpi / nodpi_and_m.png'。但事实并非如此。 - CommonsWare
3
重点是:您应该将矢量图放在drawable-anydpi-v21中。如果您使用了support-vector-drawable库,则可以将它们放在drawable-anydpi或仅放在drawable中。 - rds
2
一个drawable-nodpi文件夹的重要优点是,在默认的drawable文件夹下,高分辨率屏幕(4x,16x等)的缩放会使应用程序内存使用呈指数增长,这会给用户带来很大负担。通过检查我的游戏应用程序在drawable vs drawable-nodpi图形资产下的内存使用量,我发现了这一点。我很惊讶这个问题在任何地方都没有得到记录。 - Androidcoder
显示剩余8条评论

23

我在所有地方都使用drawable-nodpi,包括我的游戏中的许多大型图形。使用-anydpi缩放图形的一个未记录的后果是它呈指数增长地增加了内存使用量。因此,如果您在drawable中有一个1MB的图形,则会根据用户设备的分辨率将其缩放为4MB、16MB、64MB或更多。而设备分辨率不断提高。当然,这种缩放并不会实际增加图形的清晰度。通常,绘制操作可用于直接控制每个图形与屏幕大小的比例,无需使应用程序膨胀。我也不使用多个分辨率特定的绘制文件夹来节省内存和维护。


5
被低估的答案。我遇到了同样的问题:有一张大小为100KB的图片,但在加载它时经常出现OOM错误。应用程序崩溃并指出无法分配18MB!我无法理解这100KB如何变成18MB,但实际上是由于缩放造成的结果。将图像切换为 no-dpi 可以解决这个问题。 - Simon Ninon
3
在使用drawable-nodpi(或mipmap-nodpi)时,记忆方面实际上是最重要的。 - Uwe Post

18

源代码中包含以下注释(第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;
希望这能消除混淆。

12
希望这能消除您的疑惑 -- 实际上并没有。在实践中,“可以缩放到任意密度”和“不适合缩放”有何区别仍不清楚。在-nodpi目录中的可绘制图像根据其大小会被缩放,具体缩放规则取决于可绘制图像的使用方式。 - CommonsWare
我认为他们所说的“可缩放到任何密度”是指矢量可绘制对象,它们将根据需要缩放以适应任何密度,无论密度有多大。 - Vishavjeet Singh
-anydpi 的包含肯定有其原因。 - Vishavjeet Singh
3
此代码已添加至https://android.googlesource.com/platform/frameworks/base/+/31245b4%5E!/,从中可以了解到它可能修复了一些错误(bug 17007265)。我的翻译是否符合您的要求? - marcinj
2
@MarcinJędrzejewski:实际上,那个提交中的“除非有一个与所请求的密度完全匹配的配置,否则将选择最佳匹配”注释给了我一个线索。谢谢! - CommonsWare
显示剩余3条评论

16

nodpi: 适用于所有密度的资源。这些是无关密度的资源。系统不会根据当前屏幕密度标记的资源进行缩放。

anydpi: 此限定符匹配所有屏幕密度,并优先于其他限定符。这对矢量可绘制对象很有用。在API Level 21中添加。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,