android-支持多种屏幕[最佳做法] 八

支持多种屏幕的目标是创建一款在 Android 系统支持的通用屏幕尺寸上都可以 正常运行且显示良好的应用。本文档 前面各节内容介绍了 Android 系统如何使您的 应用适应屏幕配置,以及如何在不同的 屏幕配置上自定义应用的外观。本节提供另外一些提示以及有助于 确保应用针对不同屏幕配置正确缩放的 技巧概览。

下面是有关如何确保应用在 不同屏幕上正常显示的快速检查清单:

  1. 在 XML 布局文件中指定尺寸时使用 wrap_contentmatch_parent 或 dp 单位 。
  2. 不要在应用代码中使用硬编码的像素值
  3. 不要使用 AbsoluteLayout(已弃用)
  4. 为不同屏幕密度提供替代位图可绘制对象

下文将提供更详细的信息。

1. 对布局尺寸使用 wrap_content、match_parent 或 dp 单位

为 XML 布局文件中的视图定义 android:layout_width 和 android:layout_height 时,使用 "wrap_content"、 "match_parent" 或 dp 单位可确保在当前设备屏幕上为 视图提供适当的尺寸。

例如,layout_width="100dp" 的视图在 中密度屏幕上测出宽度为 100 像素,在高密度屏幕上系统会将其扩展至 150 像素宽, 因此视图在屏幕上占用的物理空间大约相同。

类似地,您应选择 sp(缩放独立的像素)来定义文本 大小。sp 缩放系数取决于用户设置,系统 会像处理 dp 一样缩放大小。

2. 不要在应用代码中使用硬编码的像素值

由于性能的原因和简化代码的需要,Android 系统使用像素作为 表示尺寸或坐标值的标准单位。这意味着, 视图的尺寸在代码中始终以像素表示,但始终基于当前的屏幕密度。 例如,如果 myView.getWidth() 返回 10,则表示视图在 当前屏幕上为 10 像素宽,但在更高密度的屏幕上,返回的值可能是 15。如果 在应用代码中使用像素值来处理预先未针对 当前屏幕密度缩放的位图,您可能需要缩放代码中使用的像素值,以与 未缩放的位图来源匹配。

如果应用在运行时操作位图或处理像素值,请参阅 下面有关其他密度注意事项的一节。

3. 不要使用 AbsoluteLayout

与其他布局小工具不同,AbsoluteLayout 会强制 使用固定位置放置其子视图,很容易导致 在不同显示屏上显示效果不好的用户界面。因此,AbsoluteLayout 在 Android 1.5(API 级别 3)上便已弃用。

您应改用 RelativeLayout,它会使用相对定位 来放置其子视图。例如,您可以指定按钮小部件显示在文本小工具的“右边”。

4. 使用尺寸和密度特定资源

虽然系统会根据当前屏幕 配置扩展布局,但您在不同的屏幕尺寸上可能要调整 UI,以及提供 针对不同密度优化的可绘制对象。这基本上是重申 本文档前面的信息。

如果需要精确控制应用在不同 屏幕配置上的外观,请在配置特定的 资源目录中调整您的布局和位图可绘制对象。例如,考虑要显示在 中密度和高密度屏幕上的图标。只需创建两种不同大小的图标 (例如中密度使用 100x100,高密度使用 150x150),然后使用适当的限定符 以适当的方向放置两个 变体:

res/drawable-mdpi/icon.png   //for medium-density screens
res/drawable-hdpi/icon.png   //for high-density screens

注:如果密度限定符在目录名称中未定义, 系统会假设该目录中的资源是针对基线中 密度而设计,对于其他密度将会适当地缩放。

如需了解有效配置限定符的更多信息,请参阅本文档前面的使用 配置限定符

其他密度注意事项


本节详细说明 Android 如何在不同 屏幕密度上对位图可绘制对象执行缩放,以及如何进一步控制在不同密度屏幕上位图的绘制。 本节信息对大多数应用应该不怎么重要,除非您的 应用在不同屏幕密度上运行或 操控图形时遇到了问题。

为更好地了解在运行时 操控图形时如何支持多种密度,您应该先了解,系统通过以下方式帮助确保正确 缩放位图:

  1. 资源(例如位图可绘制对象)的预缩放

    根据当前屏幕的密度,系统将使用您的应用中提供的任何尺寸或 密度特定资源,并且不加缩放而显示它们。如果没有可用于正确密度 的资源,系统将加载默认资源,并按需要向上或向下扩展,以 匹配当前屏幕的密度。系统假设默认资源( 没有配置限定符的目录中的资源)针对基线屏幕密度 (mdpi) 而设计, 除非它们加载自密度特定的资源目录。因此,系统 会执行预缩放,以将位图调整至适应当前屏幕 密度的大小。

    如果您请求预缩放的资源的尺寸,系统将返回 代表缩放尺寸的值。例如,针对 mdpi 屏幕以 50x50 像素 设计的位图在 hdpi 屏幕上将扩展至 75x75 像素(如果没有 用于 hdpi 的备用资源),并且系统会这样报告大小。

    有时您可能不希望 Android 预缩放 资源。避免预缩放最简单的方法是将资源放在 有 nodpi 配置限定符的资源目录中。例如:

    res/drawable-nodpi/icon.png

    当系统使用此文件夹中的 icon.png 位图时,不会 根据当前设备密度缩放。

  2. 像素尺寸和坐标的自动缩放

    应用可通过在清单中将 android:anyDensity 设置为 "false" 或者通过将 inScaled 设置为 "false" 对 Bitmap 编程来停用预缩放。在此情况下,系统在绘制时会自动缩放任何绝对的像素坐标和像素 尺寸值。缩放的目的是确保像素定义的屏幕元素仍 以它们在基线屏幕密度 (mdpi) 下的大致相同物理尺寸显示。系统会对应用透明地处理此缩放,并且 向应用报告缩放后的像素尺寸,而不是物理像素尺寸。

    例如,假设设备具有 480x800 的 WVGA 高密度屏幕,大约 与传统 HVGA 屏幕的尺寸一样,但它运行的应用停用了 预缩放。在此情况下,系统在查询屏幕尺寸时会对应用“撒谎” ,报告 320x533(屏幕密度的近似 mdpi 转换值)。然后,当 应用执行绘制操作时,例如作废从 (10,10) 到 (100, 100) 的矩形,系统会将它们缩放适当的量以转变坐标,并且实际 作废区域 (15,15) 到 (150, 150)。如果应用直接操控缩放的位图, 此差异可能会导致非预期的行为,但这被视为 确保应用最佳性能所需的合理权衡。如果遇到此 情况,请参阅将 dp 单位转换为像素 单位一节。

    通常,不应停用预缩放。支持多种 屏幕的最佳方法是采用上面如何支持 多种屏幕中所述的基本技术。

如果您的应用操控位图或以某种其他方式直接与 屏幕上的像素交互,您可能需要采取其他步骤支持不同的屏幕密度。例 如,如果您通过计算手指滑过的像素数 来响应触控手势,则需使用适当的密度独立像素值,而不是实际 像素。

缩放运行时创建的位图对象

图 5. 预缩放的位图与自动缩放的 位图比较。

如果您的应用创建内存中位图(Bitmap 对象), 系统在默认情况下假设位图是针对基线中密度屏幕而设计,然后 在绘制时自动缩放位图。当位图具有不明的密度属性时,系统会对 Bitmap 应用“自动缩放”。如果未正确 考虑当前设备的屏幕密度和指定位图的密度属性, 自动缩放可能导致缩放伪影,就像未提供备用资源一样。

要控制是否缩放运行时创建的 Bitmap,可以 使用 setDensity() 指定位图的密度, 从 DisplayMetrics传递密度常量,例如 DENSITY_HIGH 或 DENSITY_LOW

如果使用 BitmapFactory 创建 Bitmap,例如从文件或流创建,可以使用 BitmapFactory.Options 定义位图的属性(因为 它已经存在),确定系统是否要缩放或者如何缩放。例如,您可以使用 inDensity字段定义 位图设计时的密度,使用 inScaled 字段指定位图是否应缩放以 匹配当前设备的屏幕密度。

如果将 inScaled 字段设置为 false,然后停用 系统可能应用到位图的预缩放,则系统在绘制时将自动 缩放它。使用自动缩放代替预缩放可能耗用的 CPU 更多,但耗用的内存 更少。

图 5 所示为在高密度屏幕上加载低 (120)、中 (160) 和高 (240) 密度位图时预缩放和自动缩放机制产生的效果。差异 很小,因为所有位图都针对当前屏幕密度而缩放,但根据在绘制时 是预缩放还是自动缩放, 缩放后位图的外观略有不同。

注:在 Android 3.0 的更高版本中,由于图形框架的改进,应该觉察不出预缩放的位图 与自动缩放的位图之间 的差异。

将 dp 单位转换为像素单位

在某些情况下,您需要以 dp 表示尺寸,然后将它们转换为 像素。设想一个在用户 手指移动至少 16 像素之后可以识别滚动或滑动手势的应用。在基线屏幕上,用户必须移动 16 pixels / 160 dpi(等于一英寸的 1/10 或 2.5 毫米),然后才会识别该手势。在 具有高密度显示屏 (240dpi) 的设备上,用户必须移动 16 pixels / 240 dpi(等于 一英寸的 1/15 或 1.7 毫米)。此距离更短,应用因此 似乎对用户更灵敏。

要修复此问题,手势阈值必须在代码中以 dp 表示,然后 转换为实际像素。例如:

// The gesture threshold expressed in dp
private static final float GESTURE_THRESHOLD_DP = 16.0f;

// Get the screen's density scale
final float scale = getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);

// Use mGestureThreshold as a distance in pixels...

DisplayMetrics.density 字段根据当前屏幕密度指定 将 dp 单位转换为像素必须使用的缩放系数。 在中密度屏幕上,DisplayMetrics.density 等于 1.0;在高密度屏幕上,它等于 1.5;在超高密度屏幕上,等于 2.0; 在低密度屏幕上,等于 0.75。此数字是一个系数,应用其乘以 dp 单位以获取用于当前屏幕的实际像素数。(然后在转换时加上 0.5f,将该数字四舍五入到最接近的整数。)如需了解 详细信息,请参阅 DisplayMetrics 类。

但是,不能为此类事件定义任意阈值,而应 使用 ViewConfiguration 中的预缩放配置值。.

使用预缩放的配置值

您可以使用 ViewConfiguration 类访问 Android 系统使用的通常距离、 速度和时间。例如, 使用 getScaledTouchSlop() 可获取框架用作滚动阈值的距离(像素):

private static final int GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).getScaledTouchSlop();

ViewConfiguration 中以 getScaled 前缀 开头的方法确定会返回不管当前屏幕密度为何都会正常显示的 像素值。

如何在多个屏幕上测试您的应用



在发布应用之前,应在所有支持的屏幕 尺寸和密度中全面测试。Android SDK 包含可以使用的模拟器皮肤, 它们会复制您的应用可能要在其中运行的常见屏幕配置的 尺寸和密度。也可修改模拟器皮肤的默认尺寸、密度和分辨率, 以复制任何特定屏幕的特性。使用模拟器皮肤和其他 自定义配置可测试任何可能的屏幕配置,因此您无 需仅仅为了测试应用的屏幕支持而购买不同的设备。

要设置环境以测试应用的屏幕支持,应使用能模拟您希望应用支持的 屏幕尺寸和密度的模拟器皮肤和屏幕配置创建 一系列 AVD (Android Virtual Devices)。要执行此操作,可以使用 AVD Manager 创建 AVD 并使用图形界面启动它们。

要启动 Android SDK Manager,从您的 Android SDK 目录执行 SDK Manager.exe(仅在 Windows 上),或者从 <sdk>/tools/ 目录执行android(在所有平台上)。图 6 所示为用于测试不同屏幕配置的 AVD Manager(选择了 AVD)。

图 6. 一组用于测试屏幕支持的 AVD。

表 3 所示为 Android SDK 中可用的各种模拟器皮肤,可用 以模拟某些最常见的屏幕配置。

如需了解有关创建和使用 AVD 测试应用的详细信息,请参阅使用 AVD Manager 管理 AVD

表 3. Android SDK(粗体表示)及其他 代表性解决方案中模拟器皮肤提供的 各种屏幕配置

  低密度 (120), ldpi 中密度 (160), mdpi 高密度 (240), hdpi 超高密度 (320), xhdpi
屏幕 QVGA (240x320)   480x640  
正常屏幕 WQVGA400 (240x400) 
WQVGA432 (240x432)
HVGA (320x480) WVGA800 (480x800) 
WVGA854 (480x854)
 
600x1024
640x960
屏幕 WVGA800** (480x800) 
WVGA854** (480x854)
WVGA800* (480x800) 
WVGA854* (480x854)
 
600x1024
   
超大屏幕 1024x600 WXGA (1280x800)
1024x768
1280x768
1536x1152
1920x1152 
1920x1200
2048x1536
2560x1536 
2560x1600
* 要模拟此配置,在 创建使用 WVGA800 或 WVGA854 皮肤的 AVD 时请指定自定义密度 160。
** 要模拟此配置,在创建 使用 WVGA800 或 WVGA854 皮肤的 AVD 时请指定自定义密度 120。
† 此皮肤可用于 Android 3.0 平台

要查看支持任何指定屏幕配置的活动设备的相对数量,请参阅 屏幕尺寸和密度 仪表板。



我们还建议您在 设置为以接近实际设备的物理尺寸运行的模拟器中测试应用。这样 更容易比较不同尺寸和密度时的结果。要 完成此操作,需要知道计算机显示器的大约密度 (dpi), 例如 30 英寸 Dell 显示器的密度约为 96 dpi。从 AVD Manager 启动 AVD 时,可在 Launch Options 中指定用于模拟器和您的 显示器的屏幕尺寸 (dpi),如图 7 所示。


如果要在使用内置皮肤 不支持的分辨率或密度的屏幕上测试应用,可以创建使用自定义分辨率或密度的 AVD。从 AVD Manager 创建 AVD 时,指定 Resolution, 而不要选择 Built-in Skin。

从命令行启动 AVD 时,可以使用 -scale 选项指定用于 模拟器的缩放比例。例如:

emulator -avd <avd_name> -scale 96dpi

要调整模拟器的大小,可使用 -scale 选项指定代表所需缩放系数的 0.1 至 3。

如需了解从命令行创建 AVD 的更多信息,请参阅从命令行管理 AVD

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值