在Android应用中只使用XHDPI可绘制资源?

48
如果您计划在不久的将来支持LDPI、MDPI、HDPI,以及可能的XHDPI,那么只包含XHDPI可缩放的图像资源,让设备自行适应其所需的分辨率,是否可行?
我已经测试过使用Photoshop将图像资源调整为MDPI和HDPI分辨率大小后,与仅调整为XHDPI分辨率大小并由Android进行调整的结果进行比较,但是我无法看出任何差异。采取这种捷径是否会导致糟糕的设计?不用为每个图像资源调整3种不同的分辨率将非常理想。
计划使用的目标SDK版本是2.1或2.2。
敬礼 Emil

2
位图缩放的最终素材看起来会比在Photoshop中使用形状图层/图层样式等原始大小的素材要差得多。远远更糟糕。如果提供的PSD文件构建良好,最好根据源Photoshop文档创建正确大小的图像。 - Marc Edwards
7个回答

25

我认为这是一个不错的做法。我能想到的唯一缺点是小型设备上的资源开销和由于缩放而可能产生的伪影。实际上,在今年的Google IO大会上,Chris Pruett建议仅嵌入高分辨率素材,让OpenGL处理缩放。


很高兴知道这个。我现在只使用xhdpi可缩放矢量图形进行开发。有没有可能提高缩小图像的质量?一些好的插值方法会很棒。 - peter.bartos
您可以启用mipmapping,让系统在选择最佳视距时创建不同大小的纹理版本。这将增加渲染速度并减少伪影。有关更多信息,请参阅http://en.wikipedia.org/wiki/Mipmap。 - Will Kru
12
克里斯·普鲁特的引语有些误导性,因为它是关于让GPU进行降采样的游戏的。 - Warpzit
请提供克里斯·普鲁特的演讲链接 :) - fikr4n
是的,这个讨论是关于使用OpenGL而不是默认的Android组件。但本质上,为组件进行mipmap和不同分辨率的图像解决了同样的问题。您可以预先计算不同大小的位图,或者让系统在运行时进行计算(一次性操作,并通常缓存结果)。需要担心的是缩放伪影,这个讨论是关于OpenGL如何几乎总是正确地缩小,但是当它们有几秒钟的时间运行时,您可以使用更好的缩小算法,就像在Photoshop中一样,而不是几十毫秒。 - Igor Čordaš

15
从Android 1.6开始,不同密度的处理已经得到了解决,包括XHDPI(直到2.2才正式添加)。你的应用程序将首先查找与其密度匹配的图像,但它也可以查找更大的“桶”(如XHDPI),然后为您执行缩放。
最好为要支持的密度包括特定的资源。一个100x100的图像需要40kb;一个200x200的图像需要160k(未压缩)。因此,在MDPI设备上使用任何XHDPI资源都会比所需的数据量多四倍,这必须在应用程序启动时处理和准备资源时进行处理。较低的内存使用意味着更高的效率,更少的OutOfMemoryException的机会。
此外,特定类型的图像在自动缩放时会看起来很糟糕。特别是,具有细小线条或细小图案的图像将使其细节变得模糊。当您手动缩小图像时,可以选择最符合您需求的算法(线性、双立方、Lanczos等)。
如果您担心自己调整大小所需的时间,可以集成批处理或使用诸如Nine Patch Resizer之类的工具:http://code.google.com/p/9patch-resizer/

以下陈述不正确:“Android 2.1不知道XHDPI资源,因此当您的代码尝试在2.1及更早版本上使用仅限XHDPI的资源时,它会崩溃。” 我从未经历过由于缺少非XHDPI图形而导致的任何崩溃。 - Paul Lammertsma
看起来1.6及以上版本将处理XHDPI资源;我会更新答案。 - Ian G. Clifton
我一直以为这是由于使用更高的SDK级别构建应用程序,选择图形的逻辑在提供的逻辑中发生,所以它可以正常工作。是否有任何正式的文档说明这一点? - Paul Lammertsma
这个话题有什么新进展吗?因为最近我用只有XHDPI文件夹的应用在三星S4-XXHDPI设备上崩溃了。所以,我是否可以只使用xxhdpi文件夹而不是仅使用xhdpi文件夹呢。(我想知道技术上的可能性,我知道图像会失去其清晰度) - Abhinav Arora

4

我在一个简单的应用程序(为Android 2.1开发)中进行了测试,仅使用xhdpi图像,在小,中和高分辨率下都可以正常工作...即使我在Android 2.1(小分辨率)上进行了测试,也可以正常打开图像。

也许内存方面的问题是真的,所以需要有人来测试一下。


3
我个人认为,在许多应用程序中,只使用 xhdpi 文件夹就可以取得很好的效果,并且我非常支持这种方法。虽然内存开销是真实存在的,但是考虑到今天的设备,我会认为它是可以忽略不计的。而且我认为在缩小后会有一些缓存,因为我从来没有因此遇到过任何减速。仅包含一个文件夹可以大大减少 APK 的大小,这对最终用户来说是非常受欢迎的。您应该记住,某些图像将获得缩放伪影(如细节和其他内容),但我个人在我的应用程序中从未遇到过任何关键问题。另外,对于按钮等元素,请务必使用 9patch 来减少圆角上的伪影,甚至可以使用此方法略微减小图像大小。 API 级别在旧版本上不会成为问题,因为我认为在不支持它的版本中 drawable-xhdpi 被视为仅仅是 drawable。不要忽略定义一些简单可绘制的 XML,例如,使用形状即可创建渐变背景非常容易,通过这种方式您可以节省空间并避免缩放伪影。

4
给那些打负分的人一个提醒,如果你认为这个回答不正确,请放心投票,但请说明为什么你这样认为。这是因为这个答案基于个人意见,并且每次都完美解决了问题。此外,还有其他开发者使用这种方法,如果你认为这是一个不好的做法,我想他们也想知道为什么。 - Igor Čordaš

2

只有xhdpi资源是可以的。但请注意,xhdpi是在api级别9(姜饼)中引入的。也就是说,如果您的目标api级别小于等于8,则至少需要hdpi资源。


2

0

关于额外内存使用的说法是错误的。

如果你把 XHDPI 大小的可绘制对象放在 MDPI 文件夹中,那么你将会遇到内存问题。

但是,如果你在 XHDPI 文件夹中提供 XHDPI 可绘制对象,则不会使用额外的内存,因为 Android 通过跳过部分图像来降低采样率。

这种“跳过”是为什么你需要为每个你计划支持的密度提供可绘制对象以使它们看起来好看的原因。

另一方面,只有某些图像在降采样时会变得模糊(主要是小图标),因此只要图像有足够的数据可以被丢弃,它就会看起来不错。或者想象一下,如果你有一个网格作为可绘制对象,那么潜在地一些网格线可能会被丢弃,从而使图像看起来很糟糕。

最后,最好让你尝试不同的设备,然后你就可以知道哪些可绘制对象需要针对其密度提供替代资源。


2
那么Android实际上足够聪明,在执行下采样之前不会将整个图像读入内存吗?如果它只是跳过像素,那么它只进行最近邻采样?需要引用。 - Karu
我也觉得他们跳过像素很奇怪,我认为他们可能使用了其他算法,但可能是错误的,一些来源会很好。不过你可能不需要担心内存问题,因为位图数据将在本地内存中管理,而不是在Java堆上,并且即使在低端设备上,你也有足够的内存来处理大型图像。 - Igor Čordaš

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