为不同屏幕创建资源

Android 可在许多不同设备上运行,这些设备各自具有不同的分辨率、屏幕大小和屏幕密度。 Android 会执行缩放和大小调整,使应用程序在这些设备上正常运行,但这有可能会导致用户无法获得最优体验。 例如,图像的显示可能模糊,或可能未按预期放置在视图中的正确位置。

概念

若要支持多个屏幕,需要了解一些术语和概念。

  • 屏幕大小 - 用于显示应用程序的物理空间量

  • 屏幕密度 – 屏幕上任何给定区域中的像素数。 典型的度量单位是每英寸点数 (dpi)。

  • 分辨率 – 屏幕上的像素总数。 开发应用程序时,分辨率没有屏幕大小和密度的影响大。

  • 与密度无关的像素 (dp) – 一种虚拟度量单位,支持独立于密度进行布局设计。 此公式用于将 dp 转换为屏幕像素:

    px = dp × dpi ÷ 160

  • 方向 – 当屏幕的宽大于高时,屏幕的方向视为横向。 相反,纵向即屏幕的高大于宽。 在应用程序生存期内,其方向可能会随用户旋转设备而改变。

请注意,前三个概念是相关的 - 在不增加密度的情况下增加分辨率会增加屏幕大小。 但如果密度和分辨率都增加,屏幕大小有可能保持不变。 屏幕大小、密度和分辨率之间的这种关系导致屏幕支持很快复杂化。

为了帮助应对这种复杂性,Android 框架更倾向于将与密度无关的像素 (dp) 用于屏幕布局。 通过使用与密度无关的像素,UI 元素在不同密度的屏幕上看起来具有相同的物理大小。

支持各种屏幕大小和密度

Android 处理了基于每个屏幕配置正确呈现布局的大部分工作。 但是,可以采取一些措施来帮助系统更快处理。

在大多数情况下,在布局中使用与密度无关的像素而非实际像素就足以确保效果独立于密度。 Android 会在运行时将可绘制资源缩放为适当大小。 但缩放可能会导致位图显得模糊。 要解决此问题,需要针对不同密度提供备用资源。 在设计适用于多种分辨率和屏幕密度的设备时,从高分辨率或高密度的图像开始然后逐渐缩小,会更容易实现。

声明支持的屏幕大小

声明屏幕大小可确保仅支持的设备才能下载应用程序。 这可以通过在 AndroidManifest.xml 文件中设置 supports-screens 元素来实现。 此元素用于指定应用程序支持的屏幕大小。 如果应用程序能够正确放置其布局以填满屏幕,则认为支持相应屏幕。 通过使用此清单元素,对于不符合屏幕规范的设备,应用程序将不会显示在 Google Play 中。 然而应用程序仍可在屏幕不受支持的设备上运行,只是布局可能会显得模糊和像素化。

解决方案的 Properites/AndroidManifest.xml 文件中声明了支持的六种屏幕:

编辑 AndroidManifest.xml 以包含 supports-screens

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          android:versionCode="1"
          android:versionName="1.0"
          package="HelloWorld.HelloWorld">
      <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />
      <supports-screens android:resizable="true"
                        android:smallScreens="true"
                        android:normalScreens="true"
                        android:largeScreens="true" />
      <application android:allowBackup="true"
                   android:icon="@mipmap/ic_launcher"
                   android:label="@string/app_name"
                   android:roundIcon="@mipmap/ic_launcher_round"
                   android:supportsRtl="true" android:theme="@style/AppTheme">
  </application>
</manifest>

为不同的屏幕大小提供备用布局

使用备用布局,可以自定义特定屏幕大小的视图,更改组件 UI 元素的位置或大小。

从 API 级别 13 (Android 3.2) 开始,不再使用屏幕大小,而使用 swNdp 限定符。 此新限定符声明给定布局所需的空间量。 建议要在 Android 3.2 或更高版本上运行的应用程序使用这些新限定符。

例如,如果布局需要至少 700 dp 的屏幕宽度,则备用布局将位于文件夹 layout-sw700dp 中:

作为指南,以下是各种设备的一些数据:

  • 典型手机 – 320 dp:典型手机尺寸

  • 5 英寸平板电脑/“tweener”设备 – 480 dp:例如 Samsung Note

  • 7 英寸平板电脑 – 600 dp:如 Barnes & Noble Nook

  • 10 英寸平板电脑 – 720 dp:如 Motorola Xoom

对于面向最高 12 (Android 3.1) 的 API 级别的应用程序,布局应归为使用以下限定符的目录中:“小”/“常规”/“大”/“超大”(对大多数设备中可用的各种屏幕大小的归纳性描述)。 例如,下图中是用于四个不同屏幕大小的备用资源:

以下是较旧的、API 级别 13 之前的屏幕大小限定符与与密度无关的像素之间的比较:

  • 426 dp x 320 dp 为小

  • 470 dp x 320 dp 为常规

  • 640 dp x 480 dp 为大

  • 960 dp x 720 dp 为超大

API 级别 13 及以上的较新屏幕大小限定符的优先级高于 API 级别 12 及以下的较旧屏幕限定符。 对于需要跨越新旧 API 级别的应用程序,可能有必要同时使用两组限定符来创建替代资源,如下面的屏幕截图所示:

为不同的屏幕密度提供不同的位图

虽然 Android 会根据需要为设备调整位图大小,但位图本身可能无法良好地放大或缩小:可能会变得模糊或不清晰。 提供适合屏幕密度的位图可缓解此问题。

例如,下面的图像是在未提供与密度相关的资源时可能出现的布局和外观问题的示例。

没有密度资源的屏幕截图

将其与使用特定于密度的资源设计的布局进行比较:

具有特定于密度的资源的屏幕截图

使用 Android Asset Studio 创建不同密度的资源

创建这些不同密度的位图可能会有些繁琐。 因此,Google 创建了一个在线实用工具,可减少创建这些位图时的一些冗繁工作,名为 Android Asset Studio

Android Asset Studio

该网站将通过提供一张图像来帮助创建针对四种常见屏幕密度的位图。 Android Asset Studio 随后将根据一些自定义设置创建位图,然后允许以 zip 文件的形式下载它们。

多个屏幕的提示

Android 在数量庞大的设备上运行,屏幕尺寸和屏幕密度的组合更是令人眼花缭乱。 以下提示有助于最大程度减少支持各种设备所需的工作量:

  • 仅设计和开发所需内容 – 有许多不同的设备,有些设备的外形规格很少见,可能需要投入大量工作来设计和开发。 屏幕大小和密度仪表板是 Google 提供的一个页面,显示屏幕大小/屏幕密度矩阵细分数据。 此细分提供了有关如何进行开发以提供屏幕支持的见解。

  • 使用 DP 而非像素 - 如果屏幕密度改变,像素会变得很麻烦。 不要硬编码像素值。 避免使用像素单位而是使用 dp(与密度无关的像素)。

  • 尽可能避免 AbsoluteLayout - 在 API 级别 3(Android 1.5)中弃用,并会导致布局脆弱。 不应使用它。 应尝试使用更灵活的布局小组件,例如 LinearLayoutRelativeLayout 或新的 GridLayout

  • 选择一个布局方向作为默认布局方向 - 例如,不提供备用资源“布局-横”和“布局-纵”,而是将横向资源放入“布局”,将纵向资源放入“布局-纵”。

  • 将 LayoutParams 用于高度和宽度 - 在 XML 布局文件中定义 UI 元素时,相比使用像素或与密度无关的单位,使用 wrap_content 和 fill_parent 值的 Android 应用程序更容易确保在不同设备中正确显示外观。 这些维度值会导致 Android 根据需要缩放位图资源。 出于同样的原因,最好在指定 UI 元素的边距和内边距时使用与密度无关的单位。

测试多个屏幕

必须针对要支持的所有配置测试 Android 应用程序。 理想情况下,应该在实际设备上进行设备测试,但在许多情况下,这是不可能的或不切实际的。 在这种情况下,使用模拟器和为每种设备配置设置 Android 虚拟设备会非常有用。

Android SDK 提供了一些可用于创建 AVD 的模拟器皮肤,这些皮肤可以复制许多设备的尺寸、密度和分辨率。 许多硬件供应商也为他们的设备提供皮肤。

另一种选择是使用第三方测试服务的服务。 这些服务会接收一个 APK,在多个不同的设备上运行它,然后提供应用程序运行情况的反馈。