这一课程表明您如何支持不同的屏幕大小:
- 确保您的布局可以适当调整大小以适应屏幕
- 根据屏幕配置提供适当的UI布局
- 确保正确的布局,是适用于正确的屏幕
- 提供正确的位图和尺寸
使用“wrap_content”和“match_parent”
为了确保你的布局是灵活的,适应不同的屏幕尺寸,你应该使用“wrap_content”
和“match_parent”
一些视图组件的宽度和高度。如果您使用“wrap_content”
,视图的宽度或高度设置必要的最小尺寸,以适应在这种观点的内容,而“match_parent”
(又称 “fill_parent”
API级别前8)组件扩大其父视图的大小相匹配。
通过使用“wrap_content”
和“match_parent”
值的大小,而不是硬编码的大小,既可以适合只有包裹视图大小的空间又可以扩大视图以填充可用的空间。例如:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:id="@+id/linearLayout1"
android:gravity="center"
android:layout_height="50dp">
<ImageView android:id="@+id/imageView1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/logo"
android:paddingRight="30dp"
android:layout_gravity="left"
android:layout_weight="0" />
<View android:layout_height="wrap_content"
android:id="@+id/view1"
android:layout_width="wrap_content"
android:layout_weight="1" />
<Button android:id="@+id/categorybutton"
android:background="@drawable/button_bg"
android:layout_height="match_parent"
android:layout_weight="0"
android:layout_width="120dp"
style="@style/CategoryButtonStyle"/>
</LinearLayout>
<fragment android:id="@+id/headlines"
android:layout_height="fill_parent"
android:name="com.example.android.newsreader.HeadlinesFragment"
android:layout_width="match_parent" />
</LinearLayout>
注意例子中怎样使用“wrap_content
“ 和“match_parent
“组件,而不是具体 的尺寸大小 。这使得布局,以适应不同屏幕尺寸和方向。
下面就是这种布局在纵向和横向模式。注意,组件的大小自动适应宽度和高度:
Figure 1. The News Reader sample app in portrait (left) and landscape (right).
使用RelativeLayout
使用嵌套实例LinearLayout
和组合“wrap_content”
和“match_parent”
构造相当复杂的布局 。然而,LinearLayout
不能够精确地控制子控件的空间上的关系;LinearLayout中的视图
简单一个挨着一个的线性布局。如果需要子视图,在线性以外的变化为导向,更好的解决办法是
经常使用RelativeLayout,它允许你指定你的布局在组件之间的关系方面。例如,你可以对齐一个子视图的左侧和屏幕右侧的另一个视图 。
例如:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Type here:"/>
<EditText
android:id="@+id/entry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/label"/>
<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/entry"
android:layout_alignParentRight="true"
android:layout_marginLeft="10dp"
android:text="OK" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/ok"
android:layout_alignTop="@id/ok"
android:text="Cancel" />
</RelativeLayout>
图2显示了这种布局的QVGA屏幕上出现。
图3显示了一个更大的屏幕上出现。
注意,虽然元件的大小发生了变化,其两者关系被 RelativeLayout.LayoutParams保留着。
使用尺寸限定
只有这么多的方案,你可以从一个灵活的布局,或像一个在前面的章节中的相对布局。虽然这些布局适应不同的屏幕组件内和周围伸展的空间,但是无法提供最佳的用户体验为每个屏幕尺寸。因此,应用程序,不仅要实施灵活的布局,但还应该提供几种可供选择的布局,以目标不同的屏幕配置 。可以configuration qualifiers,这将允许运行时自动选择适当的资源,根据当前设备的配置(如为不同屏幕尺寸的不同版式设计)。
例如,许多应用程序,为大屏幕实现“两个窗格”(应用程序可能会显示一个窗格和内容上的另一个窗格的项目清单)的格局。平板电脑和电视有足够大的两个窗格,同时适合在屏幕上,但手机屏幕分别向他们展示。因此,要实现这些布局,你可以有以下文件:
-
res /layout/ main.xml中
,单窗格(默认)布局:
<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中
,两个窗格的布局:
<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“平板)的设备。其他布局(不包括qualifiers)将被选定为小型装置。
使用最小宽度限定
开发者对3.2 之前Android设备的困难之一是“大”屏幕尺寸,其中包括戴尔Streak,原有的Galaxy Tab,一般是7“寸平板。然而,许多应用程序可能要显示不同的布局在此类别不同的设备(如5“或者7”设备),即使它们都被认为是“大”屏幕,这就是为什么Android的推出在Android 3.2“最小宽度”限定符)。
最小宽度的限定词,让你的有一定的最小宽度 dp目标屏幕给予。例如,典型的7“平板的最小宽度600 dp,所以如果你想你的用户界面,这些屏幕上有两个窗格(但较小的屏幕上的一个单一的名单),您可以使用两个相同的布局,从上一节单个和两个窗格的布局,而是
xlargeE大小预选赛, 使用
sw600dp指示两个窗格布局屏幕上的最小宽度为600dp :
-
res /layout/ main.xml中
,单窗格(默认)布局:<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
,两个窗格的布局 :<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
(两个窗格)的布局,而较小的屏幕将选择的布局/ main.xml中
(单面板)的布局。
然而,这将无法正常工作3.2之前的设备,因为他们不识别sw600dp
大小限定符,所以你仍然需要使用xlarge
限定符。所以,你应该有一个文件名 为 res /layout-xlarge/ main.xml中
这是相同的res/layout-sw600dp/main.xml
的 。在下一节中,你会看到一种技术,可让您避免重复这样的布局文件。
使用布局别名
最小宽度的限定词是只在Android 3.2及以上。因此,你应该也还是使用抽象的大小词(small, normal, large 和 xlarge)与早期版本兼容。例如,如果你想设计你的用户界面,因此,它显示了单窗格的UI在手机上,但一个多窗格7“片和大型设备的用户界面,你必须提供这些文件:
-
res /layout/ main.xml
:单窗格 -
res/layout-xlarge:
多窗格布局 -
res/layout-sw600dp:
多窗格布局
最后两个文件是相同的,因为其中一个会由Android 3.2设备相匹配,另一种为早期版本的Android平板。
为了避免这种重复片(和由此产生的维修头痛)相同的文件,可以使用别名文件。例如,您可以定义以下布局:
-
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_layout" type="layout">@layout/twopanes_narrow</item> <bool name="has_two_panes">true</bool> </resources>
- 后者这两个文件有相同的内容,但它们实际上并不定义布局。他们只是设立
主要
是一个别名,以main_twopanes
。由于这些文件xlarge
和sw600dp
选择,它们是适用于任何的平板无论Android版 本(3.2之前匹配xlarge,3.2之后将匹配sw600dp
)。
使用方向限定
一些布局工作以及在横向和纵向的方向,但其中大多数可以从调整中受益。在新闻阅读器示例应用程序,这里是如何布局,在每个屏幕的大小和方向的行为:
- 小屏幕,竖屏:单一窗口,带有志图片
- 小屏幕,横屏:单一窗口,带有标志图片
- 7寸平板,竖屏:单窗格中,带有导航
- 7寸平板,横屏:双窗格,宽,带有导航
- 10寸平板,竖屏:双窗格,狭窄,带有导航
- 10寸平板,横屏:双窗格,宽,带有导航
因此,这些布局是指在一个XML文件中指定 res /layout
/目录中。然后分配给每个布局的各种屏幕配置,应用程序使用布局别名以配合每个配置 :
res /layout/ onepane.xml:
<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/ onepane_with_bar.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:id="@+id/linearLayout1"
android:gravity="center"
android:layout_height="50dp">
<ImageView android:id="@+id/imageView1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/logo"
android:paddingRight="30dp"
android:layout_gravity="left"
android:layout_weight="0" />
<View android:layout_height="wrap_content"
android:id="@+id/view1"
android:layout_width="wrap_content"
android:layout_weight="1" />
<Button android:id="@+id/categorybutton"
android:background="@drawable/button_bg"
android:layout_height="match_parent"
android:layout_weight="0"
android:layout_width="120dp"
style="@style/CategoryButtonStyle"/>
</LinearLayout>
<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/ twopanes.xml
:
<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>
res /layout/ twopanes_narrow.xml
:
<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="200dp"
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>
现在所有可能的布局都已被定义,它只是使用配置设定映射到每个配置正确的布局上。现在可以使用布局别名:
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-sw600dp-port/layouts.xml
:
<resources>
<item name="main_layout" type="layout">@layout/twopanes</item>
<bool name="has_two_panes">true</bool>
</resources>
res/values-xlarge-land/layouts.xml
:
<resources>
<item name="main_layout" type="layout">@layout/twopanes_narrow</item>
<bool name="has_two_panes">true</bool>
</resources>
使用9.png位图
支持不同的屏幕尺寸通常还必须有能够适应不同大小的的图像资源。例如,按钮的背景必须符合它应用于为准按钮形状。
如果使用简单的图像在可以改变大小的组件上,你会很快注意到,结果较令人印象深刻的的,因为运行时将您的图像均匀伸展或收缩。解决的办法是使用9。png位图,这是特殊格式的PNG文件,表明哪些领域可以和不能被拉长。
因此,设计将与可变大小的组件上使用的位图时,总是用9.png。要转换成一个9.png位图,你可以从一个普通的图像(图4,在清晰的4倍变焦所示)。
然后运行它通过 draw9patch
SDK的工具(这是在位于tools/
目录),您可以在其中标记应绘制像素沿左侧和顶部边界伸展的地区 。您也可以标示的地区,应举行由绘图像素沿右边和底部边界,在图5的内容。
注意沿边界的黑色像素。顶部和左侧边框的指示的地方,可拉伸图像显示的内容应放在右侧和底部边界的。
此外,通知0.9 PNG
延伸。您必须使用这个扩展,因为这是框架如何检测,这是一个九修补形象,而不是一个普通的PNG图像 。
当您应用此组件(通过设置android:background="@drawable/button" ),框架延伸正确的图像,以适应按钮的大小,如在图6中的各种大小所示。