Android开发最最蛋疼的地方莫过于需要将APP的UI适用到各种分辨率的手机上。也就是手机APP多分辨率的支持。
(Android开发文档原文地址:http://developer.android.com/guide/practices/screens_support.html)
Supporting Multiple Screens
Android runs on a variety of devices that offer different screen sizes and densities. For applications, the Android system provides a consistent development environment across devices and handles most of the work to adjust each application's user interface to the screen on which it is displayed. At the same time, the system provides APIs that allow you to control your application's UI for specific screen sizes and densities, in order to optimize your UI design for different screen configurations. For example, you might want a UI for tablets that's different from the UI for handsets.(安卓APP运行在各种个样的尺寸以及密度的设备上,对于APP来说,安卓系统提供一个在不同的设备间一致的开发环境并且处理大多数的屏幕适应工作。同时,为了最优化你针对不同的屏幕配置的UI设计,系统提供API允许开发者控制APP的UI适应不同的尺寸以及密度。举个例子:你或许想一个为平板设计的UI不同于一个为手持设备设计的UI)
Although the system performs scaling and resizing to make your application work on different screens, you should make the effort to optimize your application for different screen sizes and densities. In doing so, you maximize the user experience for all devices and your users believe that your application was actually designed for theirdevices—rather than simply stretched to fit the screen on their devices.(尽管安卓系统采取了放缩措施来使你的APP运行在不同的屏幕上,你也应该努力去优化你的UI以便使得它适应不同尺寸和密度的屏幕。这样子做的目的是为了让所有设备的用户获得最大的用户体验,让他们觉得你的应用实际上是为了他们的设备而设计的,而不是仅仅是简单的拉伸来适应他们设备的屏幕)
By following the practices described in this document, you can create an application that displays properly and provides an optimized user experience on all supported screen configurations, using a single .apk
file.(根据这片文档描述的措施,你可以创建一个在所有支持的设备上很好的展示自己,提供良好用户体验的APP——仅仅需要一个.apk安装文件)
Note: The information in this document assumes that your application is designed for Android 1.6 (API Level 4) or higher. If your application supports Android 1.5 or lower, please first readStrategies for Android 1.5. (注意:文档里面的信息只适用于Andrpd1.6以及更高的版本,如果你的APP支持Android1.5或者更低的版本,请阅读。。。)
Also, be aware that Android 3.2 has introduced new APIs that allow you to more precisely control the layout resources your application uses for different screen sizes. These new features are especially important if you're developing an application that's optimized for tablets. For details, see the section about Declaring Tablet Layouts for Android 3.2.(并且,注意Android3.2已经提供新的API来让你更加精确的控制你的布局资源,这些新的特性对于优化平板体验非常重要)
Overview of Screens Support
This section provides an overview of Android's support for multiple screens, including: an introduction to the terms and concepts used in this document and in the API, a summary of the screen configurations that the system supports, and an overview of the API and underlying screen-compatibility features.(这部分大概了解一下安卓对多分辨率的支持,包括:这份文档以及API里面用到的一些术语和概念,系统支持的屏幕配置的总结,API综览和一些屏幕适配特征)
Terms and concepts(术语和概念)
1)Screen size(屏幕大小)
Actual physical size, measured as the screen's diagonal.For simplicity, Android groups all actual screen sizes into four generalized sizes: small, normal, large, and extra large.(根据屏幕对角线实际测量的物理大小(android已经根据屏幕大小分为四类small, normal, large, extra large,比如2.8寸,3.5寸))
2)Screen density(屏幕密度)
The quantity of pixels within a physical area of the screen; usually referred to as dpi (dots per inch). For example, a "low" density screen has fewer pixels within a given physical area, compared to a "normal" or "high" density screen.For simplicity, Android groups all actual screen densities into four generalized densities: low, medium, high, and extra high.(屏幕物理区域一个单位(一般用英寸)的像素数量,一般简称dpi(每英寸上的点数,记住DPI这个概念很重要)这里android也分为四类 low, medium, high, extra high.)
3)Orientation
The orientation of the screen from the user's point of view. This is either landscape or portrait, meaning that the screen's aspect ratio is either wide or tall, respectively. Be aware that not only do different devices operate in different orientations by default, but the orientation can change at runtime when the user rotates the device.(从用户的角度看设备只有2个方向,那就是横屏和竖屏。关于横竖屏最好也要出一套相对应的UI,因为长宽比不一样,放心难度不是很大。)
4)Resolution
The total number of physical pixels on a screen. When adding support for multiple screens, applications do not work directly with resolution; applications should be concerned only with screen size and density, as specified by the generalized size and density groups.(一个物理屏幕上像素点的总数。一般我们的App不会直接使用分辨率,而是使用密度和屏幕大小。)
5)Density-independent pixel (dp)A virtual pixel unit that you should use when defining UI layout, to express layout dimensions or position in a density-independent way.(一个虚拟的单位,用来定于UI布局的。用来表述布局的尺寸或者位置。)
The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a "medium" density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160)
. For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different densities.(dip(注意dip是独立像素单位,dpi是屏幕密度)等价于一个160dpi(mdpi)的屏幕,运行时系统会根据你实际屏幕的密度来自动处理缩放。像素和dip 的转换公式为dp =px*(dpi/160) 。例如在240密度(dpi)的屏幕上一个dp等于1.5个像素(dp=px*1.5)。以后我们应该尽量使用dip单位布局,不要使用像素单位。这样会使你的app屏幕兼容性更好)
Range of screens supported
Starting with Android 1.6 (API Level 4), Android provides support for multiple screen sizes and densities, reflecting the many different screen configurations that a device may have. You can use features of the Android system to optimize your application's user interface for each screen configuration and ensure that your application not only renders properly, but provides the best user experience possible on each screen.
To simplify the way that you design your user interfaces for multiple screens, Android divides the range of actual screen sizes and densities into:
- A set of four generalized sizes: small, normal, large, and xlarge(屏幕尺寸的分类)
Note: Beginning with Android 3.2 (API level 13), these size groups are deprecated in favor of a new technique for managing screen sizes based on the available screen width. If you're developing for Android 3.2 and greater, see Declaring Tablet Layouts for Android 3.2 for more information.
- A set of four generalized densities: ldpi (low), mdpi (medium), hdpi (high), and xhdpi (extra high)(屏幕响度密度的分类)
The generalized sizes and densities are arranged around a baseline configuration that is a normal size and mdpi(medium) density.This baseline is based upon the screen configuration for the first Android-powered device, the T-Mobile G1, which has an HVGA screen (until Android 1.6, this was the only screen configuration that Android supported).
Each generalized size and density spans a range of actual screen sizes and densities. For example, two devices that both report a screen size of normal might have actual screen sizes and aspect ratios that are slightly different when measured by hand. Similarly, two devices that report a screen density of hdpi might have real pixel densities that are slightly different. Android makes these differences abstract to applications, so you can provide UI designed for the generalized sizes and densities and let the system handle any final adjustments as necessary. Figure 1 illustrates how different sizes and densities are roughly categorized into the different size and density groups.(尺寸和屏幕的分类都涵盖了一个范围,相同级别的屏幕并不一定一样大)
范围图
As you design your UI for different screen sizes, you'll discover that each design requires a minimum amount of space. So, each generalized screen size above has an associated minimum resolution that's defined by the system. These minimum sizes are in "dp" units—the same units you should use when defining your layouts—which allows the system to avoid worrying about changes in screen density.(当你设计UI的时候,你会发现每个设计需要一个最小的空间尺寸,所以,上面提及的每个屏幕尺寸都有一个由系统定义的最小分辨率。最小的尺寸的单位是dp——定义布局的时候必须使用的相同单位,使用这个单位会让你不必担心屏幕尺寸的变化)
- xlarge screens are at least 960dp x 720dp
- large screens are at least 640dp x 480dp
- normal screens are at least 470dp x 320dp
- small screens are at least 426dp x 320dp
To optimize your application's UI for the different screen sizes and densities, you can provide alternative resources for any of the generalized sizes and densities. Typically, you should provide alternative layouts for some of the different screen sizes and alternative bitmap images for different screen densities. At runtime, the system uses the appropriate resources for your application, based on the generalized size or density of the current device screen.(为了优化UI设计,需要为不同尺寸和密度的屏幕设计可选的图片资源,在运行的时候,系统会根据特定设备使用合适的资源)
Note: The characteristics that define a device's generalized screen size and density are independent from each other. For example, a WVGA high-density screen is considered a normal size screen because its physical size is about the same as the T-Mobile G1 (Android's first device and baseline screen configuration). On the other hand, a WVGA medium-density screen is considered a large size screen. Although it offers the same resolution (the same number of pixels), the WVGA medium-density screen has a lower screen density, meaning that each pixel is physically larger and, thus, the entire screen is larger than the baseline (normal size) screen.(注意,屏幕的尺寸和密度是独立的概念,之间没有关联)
Density independence
Your application achieves "density independence" when it preserves the physical size (from the user's point of view) of user interface elements when displayed on screens with different densities.(APP使用独立密度来保持UI界面组件在不同配置屏幕上的物理尺寸)
Maintaining density independence is important because, without it, a UI element (such as a button) appears physically larger on a low density screen and smaller on a high density screen. Such density-related size changes can cause problems in your application layout and usability. Figures 2 and 3 show the difference between an application when it does not provide density independence and when it does, respectively.(维持独立密度是很重要的,因为没有它,一个UI元素(比如一个按钮)会出现在一个物理屏幕很大,但密度很少的显示效果(看起来就是像是被强行放大的,失真很严重)。这样相对位置的改变会出问题)
Example application without support for different densities, as shown on low, medium, and high density screens.
Example application with good support for different densities (it's density independent), as shown on low, medium, and high density screens.
The Android system helps your application achieve density independence in two ways:(dp会自动换算)
- The system scales dp units as appropriate for the current screen density
- The system scales drawable resources to the appropriate size, based on the current screen density, if necessary
In figure 2, the text view and bitmap drawable have dimensions specified in pixels (px
units), so the views are physically larger on a low density screen and smaller on a high density screen. This is because although the actual screen sizes may be the same, the high density screen has more pixels per inch (the same amount of pixels fit in a smaller area). In figure 3, the layout dimensions are specified in density-independent pixels (dp
units). Because the baseline for density-independent pixels is a medium-density screen, the device with a medium-density screen looks the same as it does in figure 2. For the low-density and high-density screens, however, the system scales the density-independent pixel values down and up, respectively, to fit the screen as appropriate.
In most cases, you can ensure density independence in your application simply by specifying all layout dimension values in density-independent pixels (dp
units) or with "wrap_content"
, as appropriate. The system then scales bitmap drawables as appropriate in order to display at the appropriate size, based on the appropriate scaling factor for the current screen's density.
However, bitmap scaling can result in blurry or pixelated bitmaps, which you might notice in the above screenshots. To avoid these artifacts, you should provide alternative bitmap resources for different densities. For example, you should provide higher-resolution bitmaps for high-density screens and the system will use those instead of resizing the bitmap designed for medium-density screens. The following section describes more about how to supply alternative resources for different screen configurations.(bitmap的放缩会影响图片的质量,所以一般提供多套图片以供程序选择)
How to Support Multiple Screens
The foundation of Android's support for multiple screens is its ability to manage the rendering of an application's layout and bitmap drawables in an appropriate way for the current screen configuration. The system handles most of the work to render your application properly on each screen configuration by scaling layouts to fit the screen size/density and scaling bitmap drawables for the screen density, as appropriate. To more gracefully handle different screen configurations, however, you should also:
1)Explicitly declare in the manifest which screen sizes your application supports(显式声明APP支持的屏幕尺寸)
By declaring which screen sizes your application supports, you can ensure that only devices with the screens you support can download your application. Declaring support for different screen sizes can also affect how the system draws your application on larger screens—specifically, whether your application runs in screen compatibility mode.
To declare the screen sizes your application supports, you should include the <supports-screens>
element in your manifest file.
2)Provide different layouts for different screen sizes
By default, Android resizes your application layout to fit the current device screen. In most cases, this works fine. In other cases, your UI might not look as good and might need adjustments for different screen sizes. For example, on a larger screen, you might want to adjust the position and size of some elements to take advantage of the additional screen space, or on a smaller screen, you might need to adjust sizes so that everything can fit on the screen.
The configuration qualifiers you can use to provide size-specific resources are small
, normal
, large
, andxlarge
. For example, layouts for an extra large screen should go in layout-xlarge/
.
Beginning with Android 3.2 (API level 13), the above size groups are deprecated and you should instead use the sw<N>dp
configuration qualifier to define the smallest available width required by your layout resources. For example, if your multi-pane tablet layout requires at least 600dp of screen width, you should place it inlayout-sw600dp/
. Using the new techniques for declaring layout resources is discussed further in the section about Declaring Tablet Layouts for Android 3.2.
3)Provide different bitmap drawables for different screen densities
By default, Android scales your bitmap drawables (.png
, .jpg
, and .gif
files) and Nine-Patch drawables (.9.png
files) so that they render at the appropriate physical size on each device. For example, if your application provides bitmap drawables only for the baseline, medium screen density (mdpi), then the system scales them up when on a high-density screen, and scales them down when on a low-density screen. This scaling can cause artifacts in the bitmaps. To ensure your bitmaps look their best, you should include alternative versions at different resolutions for different screen densities.
The configuration qualifiers you can use for density-specific resources are ldpi
(low), mdpi
(medium), hdpi
(high), and xhdpi
(extra high). For example, bitmaps for high-density screens should go in drawable-hdpi/
.
在运行时, 对于给定资源系统使用以下这些步骤保证你最佳的显示:
- 系统会使用合适的替代资源
基于当前屏幕的大小和密度,系统会针对屏幕的密度和大小使用资源。例如,如果设备有一个 hdpi的屏幕那么当App请求一个drawable 资源时,系统会在最匹配的的设备配置下的drawable 资源目录寻找。可以取决于其他可替代的资源,使用
drawable-hdpi
的资源目录最匹配的,所以系统会使用drawable-hdpi
目录下的资源。 - 如果没有可用的匹配资源,系统会使用默认资源等比放大或缩小以匹配当前屏幕的大小和密度。
这里的默认资源是没有后缀的。例如,“
drawable
”就是默认的drawable 资源。系统会认为默认的资源都是基于normal 屏幕大小和medium 密度设计的。系统会等比缩放默认的密度资源来匹配hdpi密度或者ldpi密度。当系统没有找到针对密度资源的目录时,它就一直会使用默认的资源。例如,如果系统想找一个ldpi(低密度)的资源,但找不到。那么系统会等比缩小hdpi的资源,为什么不寻找mdpi呢?因为系统对于hdpi更容易缩放,它的系数为0.5,相比mdpi的0.75来说。0.5的的性价比更高(方便计算,正确率也高一点)。关于这一点最好的证明就是android版本的QQ浏览器。你解压后发现它关于drawable就只有drawable和drawable-hdpi两个文件夹,看来腾讯里android的开发者应该很熟悉android系统规律了,因为默认的drawable 就是mdpi,只需要定义一套hdpi的drawable
资源就行了。
从程序里面使用DisplayMetrics可以获取如下参数:
参数解释如下:
desnity = desnityDpi / 160;
dp也就是dip。这个和sp基本类似。如果设置表示长度、高度等属性时可以使用dp或sp。但如果设置字体,需要使用sp。dp是与密度无关,sp除了与密度无关外,还与scale无关。如果屏幕密度为160,这时dp和sp和px是一样的。1dp=1sp=1px,但如果使用px作单位,如果屏幕大小不变(假设还是3.2寸),而屏幕密度变成了320。那么原来TextView的宽度设成160px,在密度为320的3.2寸屏幕里看要比在密度为160的3.2寸屏幕上看短了一半。但如果设置成160dp或160sp的话。系统会自动将width属性值设置成320px的。也就是160 * 320 / 160。其中320 / 160可称为密度比例因子。也就是说,如果使用dp和sp,系统会根据屏幕密度的变化自动进行转换.
在XML布局中是可以使用dp布局的,但是在代码中不支持使用dp布局,只能使用像素布局,所以我们进行一些转化,也就是像素布局的时候需要将像素乘以dm.desnity才能在不同的分辨率上显示相同大小的组件!
补充:状态栏和标题栏的高度计算:
1 Rect frame = new Rect(); 2 getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); 3 int statusBarHeight = frame.top;//状态栏高度 4 int contentTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop(); 5 //statusBarHeight是上面所求的状态栏的高度 6 int titleBarHeight = contentTop - statusBarHeight;
代码经过验证。