Android官方提供的支持不同屏幕大小的全部方法-程序员宅基地

技术标签: ui  移动开发  

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8830286

原文地址为:http://developer.android.com/training/multiscreen/screensizes.html

本文将告诉你如何让你的应用程序支持各种不同屏幕大小,主要通过以下几种办法:

  • 让你的布局能充分的自适应屏幕
  • 根据屏幕的配置来加载合适的UI布局
  • 确保正确的布局应用在正确的设备屏幕上
  • 提供可以根据屏幕大小自动伸缩的图片

使用 "wrap_content" 和 "match_parent"

为了确保你的布局能够自适应各种不同屏幕大小,你应该在布局的视图中使用"wrap_content""match_parent"来确定它的宽和高。如果你使用了"wrap_content",相应视图的宽和高就会被设定成刚好能够包含视图中内容的最小值。而如果你使用了"match_parent"(在Android API 8之前叫作"fill_parent"),就会让视图的宽和高延伸至充满整个父布局。

通过使用"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"来给控件定义宽高的,这让整个布局可以正确地适应不同屏幕的大小,甚至是横屏。

下图是这个布局分别在竖屏和横屏时显示的结果,注意控件的宽和高是根据屏幕自适应的。


使用RelativeLayout

通过多层嵌套LinearLayout和组合使用"wrap_content""match_parent"已经可以构建出足够复杂的布局。但是LinearLayout无法允许你准确地控制子视图之前的位置关系,所有LinearLayout中的子视图只能简单的一个挨着一个地排列。如果你需要让子视图能够有更多的排列方式,而不是简单地排成一行或一列,使用RelativeLayout将会是更好的解决方案。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>
下图展示了这个布局在QVGA屏幕上显示的结果。


下图展示了这个布局在一个更大的屏幕上显示的结果。


可以注意到,即使屏幕的大小改变,视图之前的相对位置都没有改变。

使用Size限定符

虽然使用以上几种方式可以解决屏幕适配性的问题,但是那些通过伸缩控件来适应各种不同屏幕大小的布局,未必就是提供了最好的用户体验。你的应用程序应该不仅仅实现了可自适应的布局,还应该提供一些方案根据屏幕的配置来加载不同的布局,可以通过配置限定符(configuration qualifiers)来实现。配置限定符允许程序在运行时根据当前设备的配置自动加载合适的资源(比如为不同尺寸屏幕设计不同的布局)。

现在有很多的应用程序为了支持大屏设备,都会实现“two pane”模式(程序会在左侧的面板上展示一个包含子项的List,在右侧面板上展示内容)。平板和电视设备的屏幕都很大,足够同时显示两个面板,而手机屏幕一次只能显示一个面板,两个面板需要分开显示。所以,为了实现这种布局,你可能需要以下文件:

res/layout/main.xml,single-pane(默认)布局:

<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-large/main.xml,two-pane布局:
<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>
请注意第二个布局的目录名中包含了large限定符,那些被定义为大屏的设备(比如7寸以上的平板)会自动加载此布局,而小屏设备会加载另一个默认的布局。

使用Smallest-width限定符

使用Size限定符有一个问题会让很多程序员感到头疼,large到底是指多大呢?很多应用程序都希望能够更自由地为不同屏幕设备加载不同的布局,不管它们是不是被系统认定为"large"。这就是Android为什么在3.2以后引入了"Smallest-width"限定符。

Smallest-width限定符允许你设定一个具体的最小值(以dp为单位)来指定屏幕。例如,7寸的平板最小宽度是600dp,所以如果你想让你的UI在这种屏幕上显示two pane,在更小的屏幕上显示single pane,你可以使用sw600dp来表示你想在600dp以上宽度的屏幕上使用two pane模式。

res/layout/main.xml,single-pane(默认)布局:

<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布局:
<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(two-pane)布局,而更小屏幕的设备将会选择 layout/main.xml(single-pane)布局。

然而,使用早于Android 3.2系统的设备将无法识别sw600dp这个限定符,所以你还是同时需要使用large限定符。这样你就需要在res/layout-largeres/layout-sw600dp目录下都添加一个相同的main.xml。下节你将会看到如何避免重复定义这种布局的技巧。

使用布局别名

Smallest-width限定符仅在Android 3.2及之后的系统中有效。因而,你也需要同时使用Size限定符(small, normal, large和xlarge)来兼容更早的系统。例如,你想手机上显示single-pane界面,而在7寸平板和更大屏的设备上显示multi-pane界面,你需要提供以下文件:

  • res/layout/main.xml: single-pane布局
  • res/layout-large: multi-pane布局
  • res/layout-sw600dp: multi-pane布局

最后的两个文件是完全相同的,为了要解决这种重复,你需要使用别名技巧。例如,你可以定义以下布局:

  • res/layout/main.xml, single-pane布局
  • res/layout/main_twopanes.xml, two-pane布局

加入以下两个文件:

res/values-large/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。这样两个layout.xml都只是引用了@layout/main_twopanes,就避免了重复定义布局文件的情况。

使用Orientation限定符

有些布局会在横屏和竖屏的情况下都显示的很好,但是多数情况下这些布局都可以再调整的。在News Reader示例程序中,布局在不同屏幕尺寸和不同屏幕方向中是这样显示的:

  • 小屏幕, 竖屏: 单面板, 显示logo
  • 小屏幕, 横屏: 单面板, 显示logo
  • 7寸平板, 竖屏: 单面板, 显示action bar
  • 7寸平板, 横屏: 双面板, 宽, 显示action bar
  • 10寸平板, 竖屏: 双面板, 窄, 显示action bar
  • 10寸平板, 横屏: 双面板, 宽, 显示action bar
  • 电视, 横屏: 双面板, 宽, 显示action bar

所有这些布局都是定义在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-large-land/layouts.xml:
<resources>
    <item name="main_layout" type="layout">@layout/twopanes</item>
    <bool name="has_two_panes">true</bool>
</resources>
res/values-large-port/layouts.xml:
<resources>
    <item name="main_layout" type="layout">@layout/twopanes_narrow</item>
    <bool name="has_two_panes">true</bool>
</resources>

使用Nine-Patch图片

支持不同屏幕大小通常情况下也意味着,你的图片资源也需要有自适应的能力。例如,一个按钮的背景图片必须能够随着按钮大小的改变而改变。

如果你想使用普通的图片来实现上述功能,你很快就会发现结果是令人失望的,因为运行时会均匀地拉伸或压缩你的图片。解决方案是使用nine-patch图片,它是一种被特殊处理过的PNG图片,你可以指定哪些区域可以拉伸而哪些区域不可以。

因而,当你设计需要在不同大小的控件中使用的图片时,最好的方法就是用nine-patch图片。为了将图片转换成nine-patch图片,你可以从一张普通的图片开始:


然后通过SDK中带有的draw9patch工具打开这张图片(工具位置在SDK的tools目录下),你可以在图片的左边框和上边框绘制来标记哪些区域可以被拉伸。你也可以在图片的右边框和下边框绘制来标记内容需要放置在哪个区域。结果如下图所示:


注意图片边框上的黑色像素,在上边框和左边框的部分表示当图片需要拉伸时就拉伸黑点标记的位置。在下边框和右边框的部分表示内容将会被放置的区域。

同时需要注意,这张图片的后缀名是 .9.png。你必须要使用这个后缀名,因为系统就是根据这个来区别nine-patch图片和普通的PNG图片的。

当你需要在一个控件中使用nine-patch图片时(如android:background="@drawable/button"),系统就会根据控件的大小自动地拉伸你想要拉伸的部分,效果如下图所示:


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/iteye_7514/article/details/82488903

智能推荐

0-1背包问题的迭代回溯算法实现(C++)_0-1背包问题的回溯算法设计c语言-程序员宅基地

文章浏览阅读1.1k次。编译环境:Dev-C++迭代回溯方法求解0-1背包问题的具体算法实现_0-1背包问题的回溯算法设计c语言

Ubuntu12.10开机输入密码后黑屏无法进入桌面的问题记录_lightdm输入密码后进不去dwm-程序员宅基地

文章浏览阅读2.4k次。Ubuntu12.10安装系统的中文语音的时候一直卡住,安装不上,按我这个急性子不小心我把整个系统关闭了,再重启系统后,当进入账号界面输入正确密码后,电脑一直黑屏,无法进入桌面(可以看到鼠标)。上网查了一些方法试了不行:比如如下:图形界面程序损坏,可能是在更新内核或者安装软件的时候,把与xorg相关的文件给清除了。系统黑屏后 Ctrl+ALT+F4 进入 命令行模式sudo..._lightdm输入密码后进不去dwm

go语言web开发系列之十六:gin框架中通过gorm使用事务_gorm 事务-程序员宅基地

文章浏览阅读5.4k次,点赞7次,收藏24次。一,演示项目的相关信息1,地址:https://github.com/liuhongdi/digv162,功能:以下订单为例,演示了在gorm中启用事务3, 项目结构:如图:说明:刘宏缔的go森林是一个专注golang的博客, 地址:https://blog.csdn.net/weixin_43881017说明:作者:刘宏缔 邮箱: [email protected]二,数据库及sql1,数据表:2,建表sql:CREATE TABLE `..._gorm 事务

线性二次型调节控制-程序员宅基地

文章浏览阅读200次。线性二次型调节控制现在我们讨论一个用于连续状态MDP的一个寻找最优策略的一个方法。该方法中我们直接近似V∗,而不采用离散化。该方法称之为值函数近似,在很多实际RL问题都有很好的应用。使用一个模型或为了发展一个值函数近似算法,我们假设对于MDP,我们有一个模型(model)或仿真器(simulator)。通俗的说,一个仿真器是一个黑盒子,输入是任何一个连续值的状态st,动作at,..._线性二次型调节器优势

分位数回归-Quantile regression-程序员宅基地

文章浏览阅读5.3w次,点赞29次,收藏187次。文章目录一、分位数回归概念二、相关推导2.1 分位数概念2.2 离差绝对值LAD2.3 分位数回归2.4 效果以及理解三、模型检验四、求解方法一、分位数回归概念分位数回归是估计一组回归变量X与被解释变量Y的分位数之间线性关系的建模方法。以往的回归模型实际上是研究被解释变量的条件期望。而人们也关心解释变量与被解释变量分布的中位数,分位数呈何种关系。它最早由Koenker和Bassett(197..._分位数回归

北理 计算机学院 钟宏,袁汉宁_北京理工大学计算机学院-程序员宅基地

文章浏览阅读139次。代表性学术成果[1] Hanning Yuan, Meng Fang,Xinquan Zhu,Hierarchical Sampling for Multi-Instance Ensemble Learning, IEEE Transactions on Knowledge and Data Engineering, 2013,25(12):2900~2905(SCI/Ei)[2] Hanning..._北京理工大学袁汉宁

随便推点

html css 隐藏div显示,css如何隐藏div?-程序员宅基地

文章浏览阅读939次。在我们平时布局网站的时候,想要把div进行隐藏,但是很多人不知道css控制div显示隐藏?下面我们来讲解一下css如何让div隐藏。一:使用display:none属性来隐藏div我们可以使用display:none属性来隐藏所有的信息,包括文本和图片,语法为:这里你是看不到的当我们使用div中的css样式,我们就可以使用display:none属性对内容进行隐藏,并且通过浏览器也是看不到的,同时..._隐藏 css

二、animate.css动画插件_css3动画插件-程序员宅基地

文章浏览阅读1.6k次。css3动画库,预设了抖动(shake)、闪烁(flash)、弹跳(bounce)、旋转(rotateIn|rotateOut)、翻转(flip)、淡入淡出(fadeIn|fadeOut)等动画效果。1、过渡动画是需要触发条件的(hover事件或click事件等),只能完成简单的动画。2、加统一的类名animated,然后选择自己想要的动画效果,然后复制粘贴。第一个animated是必须添加的样式名,第二个是指定的动画样式名。2、帧动画不需要任何的触发条件,可以完成复杂轨迹的动画。_css3动画插件

分享5个插件,助你在Python的道路越战越勇_python插件大全-程序员宅基地

文章浏览阅读1.1w次,点赞80次,收藏300次。你所不知道的编程插件,看完直呼内行_python插件大全

长连接简单使用;_一看特别长的链接怎么用-程序员宅基地

文章浏览阅读730次。很多IM应用中会用到这个东西,然而真正自己搭建IM应用服务端的很少,一般都是找的IM云,环信,融云,网易云信……不可否认,基础工能实现几家平台做的都很好,有幸用过网易云信,当时只是看别人文档,复制demo代码。搭建界面而已,没有想过内部实现原理。突然研究这个东西的时候,就会发现 长连接不一定只是用在IM上面的,所以了解一下简单实现原理,还是对更多功能的接入,有很大帮助的。Asy_一看特别长的链接怎么用

Android :clang.exe: error: linker command failed with exit code 1 (use -v to see invocation)_android clang: error: linker command failed with e-程序员宅基地

文章浏览阅读3.2k次。 今天在使用Android Studio3.0.1 ,升级了build:gradle 后,编译项目报错:clang.exe: error: linker command failed with exit code 1 (use -v to see invocation) ninja:build stopped:subcommand failed. FAILURE: Build f..._android clang: error: linker command failed with exit code 1 (use -v to see

ubuntu 8.04 bochs 调试linux 0.11内核_gcc4 hdc-0.11 hdc-0.11.img-程序员宅基地

文章浏览阅读1.8k次。要下载的软件包:bochs-2.3.5linux-0.11-081030.tar.gz linux-0.11-devel-060625.zip(hdc-0.11-new.img 文件系统)(hdc-0.11-new.img 只用这一个文件也可以时入linux 0.11系统,只需在配置bochs时稍做修改就可以,但是要调试源码的话,还是自己编译来得爽)安装bochs之前做一些_gcc4 hdc-0.11 hdc-0.11.img

推荐文章

热门文章

相关标签