首先你需要了解屏幕密度和屏幕尺寸的区别。
屏幕尺寸是物理尺寸,以屏幕的对角线测量。Android 将所有实际屏幕尺寸分为四种通用尺寸:小、普通、大和特大。一部手机的屏幕尺寸可能为 4.9 英寸,这被认为是正常的,Nexus 7(2012 年的旧款和 2013 年的新款)的屏幕尺寸都是 7 英寸,这很大,Nexus 10 的屏幕尺寸10 英寸,这是超大的。
另一方面,屏幕密度是屏幕物理区域内的像素数量;通常称为 dpi(每英寸点数)。例如,与“正常”或“高”密度屏幕相比,“低”密度屏幕在给定物理区域内的像素较少。为简单起见,Android 将所有实际屏幕密度分为四种通用密度:低、中、高和超高(加上新的 xxhdpi)。旧的 Nexus 7 的屏幕尺寸与新的 Nexus 7 相同,但旧的分辨率为 1280x800,即 216 dpi 或 hdpi,而新的分辨率为 1920×1200 像素,即 323 dpi 或 xhdpi(更多像素在同一物理区域内意味着更高的 dpi 像素密度)。
如果屏幕具有相同的屏幕密度,则可绘制文件夹中的图像在小屏幕、普通屏幕、大屏幕和超大屏幕上将具有相同的物理尺寸。因为屏幕具有不同的尺寸,所以图像将占据屏幕的不同部分。在小屏幕上,它会比在大屏幕上占据更大的百分比。
如果相同的图像位于屏幕大小的文件夹之一(drawable-small、drawable-normal、drawable-large、drawable-xlarge)中,则不会发生任何变化,但您可以决定将较大版本的图像放在 drawable-xlarge 中。在这种情况下,Nexus 10 上的图像会比新 Nexus 7 上的大(两者都有 xhdpi 像素密度)。
如果屏幕具有不同的像素密度,则相同的图像看起来会有所不同。与 mdpi 屏幕相比,xhdpi 屏幕上的图像大小只有一半(因为 xhdpi 屏幕的像素密度大约是两倍):http:
//developer.android.com/images/screens_support/density-test-bad.png
对于一个图标,您通常希望它在不同的屏幕上具有相同的大小。这就是为什么 mdpi 屏幕的菜单图标是 32x32 而 xhdpi 屏幕的菜单图标是 64x64 并且两者都在适当的可绘制文件夹(drawable-mdpi 和 drawable-xhdpi)中:http:
//developer.android.com/images/screens_support/density -test-good.png
现在什么时候使用像素密度,什么时候使用屏幕大小的可绘制文件夹?
如果图像在具有不同屏幕密度的屏幕上应具有相同的物理尺寸,则使用像素密度文件夹,这通常是您想要的。如果您对旧的和新的 Nexus 7 使用相同的图像,即使屏幕具有相同的物理尺寸,它也会有不同的尺寸,这不是您想要的。因此,使用密度相关图像势在必行。
如果您希望图像在小、普通、大和超大屏幕上具有不同的物理尺寸,则使用屏幕尺寸文件夹。如果我在主屏幕上有一个带有 6 个图标的网格导航,并且我不想在大屏幕上使用额外的屏幕空间(例如通过添加更多图标),那么我会为小屏幕提供一个小图像和大屏幕的大图像。如前所述,您仍然必须在依赖于屏幕尺寸的图像之上提供依赖于密度的图像(例如旧的 Nexus 7 与新的 Nexus 7)。
所以理论上你需要 16 个不同的资源来处理同一个图像(4 个屏幕尺寸,4 个屏幕密度,或者使用新的 xxhdpi 密度,甚至 5 个密度 -> 20 个资源)。现在当然没有人想创建那么多资源,尤其是如果你有很多图像。一种方法是按照某人的建议使用仪表板:http:
//developer.android.com/about/dashboards/index.html#Screens
并选择最常用的组合,即 small/ldpi、normal/mdpi、normal/ hdpi 和 normal/xhdpi(所有设备的 81%)。这样你就可以将资源减少到只有 4
个。另一种方法是为屏幕大小或屏幕密度提供资源(同样只需要 4 个资源),然后在代码中进行一些缩放。
如果您有与屏幕密度相关的资源,那么您将使用例如此https://stackoverflow.com/a/5016350/534471来缩小图像(从不放大)。
如果您有依赖于屏幕尺寸的资源,那么您将使用此http://developer.android.com/reference/android/util/DisplayMetrics.html
来缩小图像。
这里有一个很好的例子(包括源代码):
https ://www.captechconsulting.com/blog/steven-byle/understanding-density-independence-android
现在,对于您的具体问题,您可以在可绘制文件夹中使用一个通用图像。该图像的大小应该不会被放大(因为那看起来很难看)。您可以像这样在布局中定义按钮:
<ImageButton
android:id="@+id/myButton"
android:src="@drawable/myDrawable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
/>
连同这段代码,按钮缩放到屏幕的 10%:
Display display = getWindowManager().getDefaultDisplay();
Point screenSize = new Point();
display.getRealSize(screenSize);
int size = Math.min(screenSize.x, screenSize.y);
int buttonSize = Math.round(size * 0.1f);
ImageButton button = (ImageButton) findViewById(R.id.myButton);
button.setMaxWidth(buttonSize);
button.setMaxHeight(buttonSize);
原图应该多大?
Nexus 10 可能是目前所有 Android 设备中屏幕分辨率最高的。1600 像素将在其 xhdpi 显示器上转换为 3200 密度独立像素。3200 的 10% 是 320。如果您使用 320x320 图像,那么您将在所有现有设备上获得良好的结果。
不过,这种方法有一个问题。
320x320 相当大(可能是 24/32 位色深),因此您可能会遇到内存问题。如果您在与密度相关的可绘制文件夹中提供相同的资源,您可以降低 hdpi、mdpi 和 ldpi 设备的内存占用:
- 可绘制 xhdpi:320x320
- 可绘制的 hdpi:240x240
- 可绘制 mdpi:160x160
- 可绘制的 ldpi:120x120
屏幕大小的可绘制文件夹可用于进一步改善这一点(较小的屏幕需要较小的图像),但您必须提供前面提到的 16 或 20 个资源。最后,它是一方面的内存占用/速度与另一方面的可维护性/创建资源/ apk 大小的时间之间的权衡。