前记:Android现在拥有数百种不同屏幕尺寸的设备,小到手机,大到电视。因此,设计你的程序适合所有屏幕尺寸显得很重要,以便于尽可能多的用户使用。但是适应不同设备类型是不可能的,每个屏幕给用户的交互都有很多可能性和带来挑战,所以为了满足和尊重你的用户,你的用户程序要能适应大部分屏幕,优化用户在每个屏幕的方向体验。下面介绍如何实现用户交互用于优化几种屏幕方向。
今天首先介绍的是如何使你的应用程序支持多种屏幕尺寸的方法。这也是我前几天面试时遇到的问题,当时写了几个,没写全。然后又看了官方文档,翻译一下,也算是对android开发总结一下。
总的来说提供了七种方法,分别是:
- 使用“wrap_content”和“match_parent”(也就是fill_parent);
- 使用RelativeLayout布局;
- 使用Size Qualifiers(尺寸修饰符);
- 使用 Smallest-width Qualifiers(小宽度修饰符);
- 使用Layout Aliases(布局的别名)
- 使用Orientation Qualifiers(方向修饰符);
- 使用 Nine-patch BitMaps(.9.png图片);
注意:“wrap_content”和“fill_parent”用于组件的大小而不是特定的尺寸,这允许布局正确适应不同屏幕尺寸和方向。
2.使用相对布局:
你可以使用嵌套的LinearLayout(线性布局)和组合“wrap-content ”和“fill_parent”构造复杂的布局。但是,LinearLayout不允许你精确地控制子视图的空间位置关系,在LinearLayout中的子view一列一列的排下去。如果你希望子view的方向是可变更的而不是在一条直线上,最好的解决方法是经常使用的RelativeLayout(相对布局)。
3.使用尺寸修饰符:
其实距离你想得到的灵活多变布局距离还很远,前面介绍的两个方法并不能很好解决这个问题。它不可能给不同屏幕尺寸提供很好的用户体验。因此你的应用程序不应当仅仅为了实现灵活多变的布局,应该提供几种可供选择的布局给不同屏幕尺寸。你可以使用Configuration qualifiers(配置修饰符),允许运行的时候自动选择合适的资源根据当前的设备配置。(不同的布局用于不同屏幕尺寸)
例如,许多应用程序都实现了“two panes”(两个窗口)模式用于大屏幕(应用程序在一个窗口显示列表清单,在另一个窗口显示内容)。平板和电视同时显示两个窗口是足够的,但是手机屏幕只能分开实现他们。所以,为了实现这些布局,你可以写两个布局如下:
res/layout/main.xml
, single-pane (default) layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/headlines" android:layout_height="fill_parent" android:name="com.example.android.newsreader.HeadlinesFragment" android:layout_width="match_parent" /> </LinearLayout>
res/layout-xlarge/main.xml
, two-pane layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal"> <fragment android:id="@+id/headlines" android:layout_height="fill_parent" android:name="com.example.android.newsreader.HeadlinesFragment" android:layout_width="400dp" android:layout_marginRight="10dp"/> <fragment android:id="@+id/article" android:layout_height="fill_parent" android:name="com.example.android.newsreader.ArticleFragment" android:layout_width="fill_parent" /> </LinearLayout>
注意:在第二个布局路径名中的 xlarge修饰符。这个布局是被选用在定义为大屏幕的设备上(例如,10寸的平板),第一个布局被选用在小屏幕设备上。
4.使用小宽度修饰符:
在3.2之前的Android设备中,开发者遇到的困难之一就是“大”屏幕尺寸,包含Galaxy系列平板,通常是7寸的平板。然而,许多应用程序想在不同的设备上显示不同布局(例如5寸的、7寸的设备),尽管它们被认为是大屏幕。这也是Android在3.2中引进“Smallest-width”修饰符(介于大屏幕和小屏幕之间的)。
这Smallest-width修饰符允许你匹配给定最小限度宽度以dp为单位的屏幕。例如,通常7寸的平板,有600dp宽度最小限制,所以如果你想要你的UI有两个窗口在这些屏幕上(在小屏幕上显示单个列表),你可以使用前面介绍的两个布局(单个和两个窗口布局),但是使用sw600dp代替xlarge修饰符,表示两个窗口布局适用于屏幕最小宽度为600dp。
res/layout/main.xml
, single-pane (default) layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/headlines" android:layout_height="fill_parent" android:name="com.example.android.newsreader.HeadlinesFragment" android:layout_width="match_parent" /> </LinearLayout>
res/layout-sw600dp/main.xml
, two-pane layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal"> <fragment android:id="@+id/headlines" android:layout_height="fill_parent" android:name="com.example.android.newsreader.HeadlinesFragment" android:layout_width="400dp" android:layout_marginRight="10dp"/> <fragment android:id="@+id/article" android:layout_height="fill_parent" android:name="com.example.android.newsreader.ArticleFragment" android:layout_width="fill_parent" /> </LinearLayout>
这意味着屏幕最小宽度大于等于600dp选择使用layout-sw600dp/main.xml文件作为布局,小屏幕会使用第一个布局文件。
注意:这个方法不适用于android3.2之前的版本,因为之前的版本是无法识别sw600dp这个修饰符,所以你只能使用xlarge这个修饰符。
5.使用布局的别名:
Smallest-width修饰符只适用于android3.2版本及以上。因此,你还是使用抽象大小容器(小,正常,大,特别大)适用于早期的版本。例如,如果你想设计你的UI便于显示单个窗口在手机上,显示多个窗口在7寸平板上和更大的设备上,你必须满足下面这些文件:
- res/layout/main.xml:单个窗口
- res/layout-xlarge:多个窗口
- res/layout-sw600dp:多个窗口
为了避免在平板上有重复文件(和由它导致的维护头疼问题),你可以重新命名文件。例如,你可以定义下面布局文件:
- res/layout/main.xml:单个窗口
- res/layout/main_twopanes.xml:两个窗口
- res/values-xlarge/layout.xml
<resources> <item name="main" type="layout">@layout/main_twopanes</item> </resources>
res/values-sw600dp/layout.xml
:
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
这后面两个文件有完全相同的内容,但是实际上并没有重新定义这个布局,仅仅将main命名为main_twopanes。因此这些文件就有了xlarge和sw600dp选择了。这样就满足了平板和系统版本无关(3.2之前的匹配xlarge,3.2之后的匹配sw600dp)。
6.使用方向修饰符:
一些布局在水平方向和垂直方向上效果很好,但是大多数是得益于调整。在样例程序中,布局在不同屏幕尺寸和方向的行为表现:
- 小屏幕、垂直:单窗口带有logo
- 小屏幕、水平:单窗口带有logo
- 7寸平板、垂直:单窗口、action bar
- 7寸平板、水平:双窗口、action bar
- 10寸平板、垂直:双窗口、狭窄、action bar
- 10寸平板、水平:双窗口、宽、action bar
res/layout/twopanes.xmlres/layout/twopanes_narrow.xml
:
现在可能的所有布局都定义了,接下来就是用方向修饰符匹配正确的布局到每个方向。你可以使用布局别名方法:
res/values/layouts.xml
:<resources> <item name="main_layout" type="layout">@layout/onepane_with_bar</item> <bool name="has_two_panes">false</bool> </resources>
res/values-sw600dp-land/layouts.xml
:<resources> <item name="main_layout" type="layout">@layout/twopanes</item> <bool name="has_two_panes">true</bool> </resources>
res/values-sw600dp-port/layouts.xml
:<resources> <item name="main_layout" type="layout">@layout/onepane</item> <bool name="has_two_panes">false</bool> </resources>
res/values-xlarge-land/layouts.xml
:<resources> <item name="main_layout" type="layout">@layout/twopanes</item> <bool name="has_two_panes">true</bool> </resources>
res/values-xlarge-port/layouts.xml
:7.使用.9.png图片<resources> <item name="main_layout" type="layout">@layout/twopanes_narrow</item> <bool name="has_two_panes">true</bool> </resources>
适用于不同的屏幕尺寸意味着你的图片资源也要适合不同屏幕尺寸。例如一个按钮背景图片必须适合无论什么样的按钮形状。
如果你使用一张简单的图片在一个可变大小的组件上,你会发现结果是不如人意的,因为程序运行的时候会拉伸或者缩小你的图片。解决方法也就是使用9.pn图片(一种特别格式的png文件,表示哪些区域可被拉伸,哪些不可以)。如何使用.9.png可以自己百度,也可参照我另一篇文章如何使用.9.png图片