我正在为平板电脑 7 英寸 Kindle Fire HD 和 Nexus 7 开发应用程序。这两个应用程序具有相同的大小和相同的屏幕分辨率。但是,我运行我的应用程序,它是非常不同的。为什么?
这似乎是因为nexus 7被检测为TVDPI,而Kindle Fire HD是HDPI。如何基于模型 1280 * 800 进行相同的渲染?
谢谢
我正在为平板电脑 7 英寸 Kindle Fire HD 和 Nexus 7 开发应用程序。这两个应用程序具有相同的大小和相同的屏幕分辨率。但是,我运行我的应用程序,它是非常不同的。为什么?
这似乎是因为nexus 7被检测为TVDPI,而Kindle Fire HD是HDPI。如何基于模型 1280 * 800 进行相同的渲染?
谢谢
好吧,看来您已经发现了为什么两者存在差异,这是因为它们报告了不同的密度比例因子:
那么,当它们在技术上具有相同的物理尺寸和分辨率时,为什么它们会报告不同的结果呢?
CORE 问题实际上存在,因为一台设备是 Google Play 设备 (Nexus),而另一台不是 (Kindle)。所有具有 Google Play(和其他 Google 应用程序)的 Android 设备只能通过称为兼容性测试套件 (CTS) 的东西来做到这一点,该套件会验证此类设置是否符合他们提出的标准。标准本身记录在每个版本的兼容性定义文档 (CDD) 中。 这是 Android 4.0 的 CDD 的链接(第 7.1 节涉及屏幕尺寸和密度)。CDD 告诉设备制造商他们应该报告数字上最接近屏幕实际 DPI 的比例因子,在这种情况下实际上是 TVDPI。
亚马逊设备不使用任何 Google 应用程序,包括 Google Play。虽然遵循相同的标准可能符合他们的最大利益,但他们不受这些标准的约束,而且通常不被遵循。当 TVDPI 出现在 Nexus 7 上时,每个人都在偷偷摸摸,但如果亚马逊在设计过程中引用了 CDD,他们就会知道这一点。
这如何导致他们表现不同?
差异不在您的布局选择中。显然,从您的屏幕截图来看,这两种设备都按照您的预期选择了正确的布局。更改sw
布局目录上的值只会影响哪些设备将选择该布局......它不会改变任何关于事物如何缩放的内容。不要费心尝试将布局本身放置在密度特定的目录中......布局应该是灵活的。
相反,问题在于在与密度无关的像素单元(即 dip 或 dp)上进行的任何尺寸或尺寸计算,例如文本尺寸、您可能创建的任何固定视图尺寸以及可绘制尺寸。
因为这两种设备选择了不同的资源缩放,所以您使用的任何可绘制资源或您在“dp”中定义的任何值都会导致微小的变化。让我举两个例子:
您定义 a 的文本大小TextView
为16dp
。在 Nexus 7 上,这将在 21 像素处绘制文本。Kindle Fire HD 将以 24 像素绘制相同的文本。差异很小......但它存在。
可绘制图像也是如此。如果您只drawable-mdpi
在 48x48中定义了一个图像,而drawable-hdpi
在 72x72 中定义了相同的图像,Kindle 有一个 72px 的图像可以直接使用,而 Nexus 会创建一个比例为 64px 的图像,因此两个资产之间存在 8 个像素的差异。
我该怎么做才能使两者看起来更相似?
在大多数情况下,我会说你不应该。通常,所做的缩放不会在很大程度上影响应用程序的结果,除非布局的约束设置了太多的硬编码大小。
但是,一般而言,如果您需要为此目的专门更改 UI 的某些部分,则解决方案是为-tvdpi
您认为需要它们的情况定义特定的资源和维度(同样,我不建议扩展所有内容)你的应用程序来满足这种情况)。
对于文本或视图大小等内容,这意味着您可能需要一个values-tvdpi/dimensions.xml
文件和一个默认values/dimensions.xml
文件。使用上面的示例,您可以将默认文本大小定义为 16dp,但在该-tvdpi
位置,定义与 18dp 相同的尺寸。这将导致两个设备将最终文本缩放到 24 像素。在使用实际尺寸的代码中,将其作为@dimen/myTextSize
而不是16dp
直接引用。
对于可绘制项目,添加一个drawable-tvdpi
目录并缩放这些资产以匹配您认为它们应该在 Nexus 7 等设备上绘制的方式。再次与我们之前的示例一样,将相同的图像文件从drawable-hdpi
文件夹复制到drawable-tvdpi
文件夹中,这样两个设备将绘制相同的图片为 72 像素。
为避免在多个位置复制相同的资产,您还可以使用别名来执行此操作。将图像本身放入drawable/
一个特殊的名称中,并在两个地方使用values-tvdpi/drawables.xml
和values-hdpi/drawables.xml
引用单个资产。有关别名的更多信息,请参阅此文档。这些示例适用于布局,但相同的范例适用于可绘制对象(或任何资源),方法是更改为type="drawable"
.
因为 Nexus7 是 tvdpi 设备,它使用 layout-sw600dp 资源(基于 213dpi 计算),FireHD 是 HDPI 设备并最终使用 layout-sw533dp 资源(基于 240dpi 计算)
也许您应该使用 layout-tvdpi 和 layout-hdpi?