
2.3 添加图像资源
适配多种屏幕密度和尺寸是Android中最有趣的挑战之一。当显示位图图像时尤其如此,其中有两个互斥的问题需要解决。
❑ 低分辨率图像在拉伸到适合大屏幕或高分辨率屏幕时,显示得很模糊。
❑ 在小屏幕、低密度屏幕上显示时,高质量图像所消耗的内存远远超过所需。
除屏幕尺寸外,不同屏幕密度的问题主要通过使用密度无关像素(dp)来解决。
2.3.1 管理屏幕密度
dp是基于160dpi屏幕的抽象测量单位。dp意味着无论屏幕密度如何,宽度为320dp的小部件总是2英寸
宽。当涉及屏幕的实际物理尺寸时,屏幕密度可以使用各种布局类型、支持库以及属性(如weight和gravity)来管理。下面来看如何提供图像,以适应最广泛的屏幕密度范围。
Android系统使用以下限定符划分屏幕密度:
❑ 低密度(ldpi)——120dpi
❑ 中密度(mdpi)——160dpi
❑ 高密度(hdpi)——240dpi
❑ 超高密度(xhdpi)——320dpi
❑ 超超高密度(xxhdpi)——480dpi
❑ 超超超高密度(xxxhdpi)——640dpi
在安装应用程序的过程中,每个设备只会下载符合其规格的图像。这样不仅可以节省旧设备上的内存,而且可以为有能力的设备提供最丰富的视觉体验。
从开发者的角度来看,似乎需要为给定项目中的所有图像都生成6个版本。值得庆幸的是,情况通常并非如此。在大多数手持设备上,640dpi的图像和320dpi的图像之间的差别并不明显。而且,考虑到我们的“三明治制作应用程序”的大多数用户只需要通过滑动浏览菜单上的原料,而不需要仔细观察图像的质量,我们可以仅为中、高和超高密度设备提供图像。
在考虑高端设备的图像质量时,一条经验法则是将我们的图像大小与该设备原生摄像头生成的图像大小进行比较。为了提供更大的图像以改善用户体验而增加内存需求很可能不值得。
在本示例中,我们将提供适合卡片视图的图像,该视图将在纵向模式下占据大部分屏幕宽度。现在,需要找到一幅大约2000像素宽的图像。在下面的示例中,该图像被称为sandwich.png,它的尺寸为1920像素×1080像素。你的图像不需要和该图像的尺寸保持一致,但稍后我们将看到,精心选择的图像比例是良好用户界面实践的重要组成部分。
一幅宽度为1920像素的图像,在320dpi的超高密度设备上显示的宽度为6英寸。至少现在我们可以假设应用程序将通过移动设备访问,而不是通过计算机或电视访问。因此,即使在10英寸的高密度平板计算机上,6英寸也足以满足需求。接下来看看如何为其他屏幕密度做准备。
2.3.2 使用指定资源
通过在指定资源目录中存放为特定屏幕密度配置的图像,可以轻松地得到适合各种屏幕密度的位图。在Android Studio中,可以通过以下步骤从项目资源管理器创建指定资源目录。
(1)首先,在res文件夹下创建一个新的目录,并将其命名为drawable-mdpi。
(2)接下来,创建另外两个名为drawable-hdpi和drawable-xhdpi的同级目录。
(3)通过在项目资源管理器的drawable上下文菜单中选择Show in Explorer(在资源管理器中显示),直接打开这些新文件夹。
(4)将sandwich.png图像添加到drawable-xhdpi文件夹中。
(5)把这张图像复制两份,并按与原图3∶4和1∶2比例分别缩放。
(6)将副本分别放在drawable-hdpi和drawable-mdpi目录中。
现在,这些变体将体现在项目资源管理器中,如图2-5所示。

图2-5
现在我们可以放心,应用程序只会根据设备的屏幕密度下载最适合、内存效率最高的图像资源。要查看图像,请将以下图像视图添加到项目的activity_main.xml文件中。
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/sandwich" />
可以在模拟器或真机上的预览屏幕查看输出,如图2-6所示。

图2-6
这种方法的好处在于,一旦正确指定了图像的变体,就可以简单地将其称为@drawable/sandwich,并且可以忽略它当前所在的真机或它存储在哪个目录中。
这使得我们可以自由地探索如何将图像作为界面的一部分。