文档章节

Android官方提供的支持不同屏幕大小的全部方法

jdroid
 jdroid
发布于 2014/05/02 10:44
字数 3072
阅读 832
收藏 32
点赞 0
评论 1

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

  • 让你的布局能充分的自适应屏幕

  • 根据屏幕的配置来加载合适的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" 来给控件定义宽高的,这让整个布局可以正确地适应不同屏幕的大小,甚至是横屏。

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

Android官方提供的支持不同屏幕大小的全部方法

使用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屏幕上显示的结果。

Android官方提供的支持不同屏幕大小的全部方法

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

Android官方提供的支持不同屏幕大小的全部方法

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

使用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图片,你可以从一张普通的图片开始:

Android官方提供的支持不同屏幕大小的全部方法

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

Android官方提供的支持不同屏幕大小的全部方法

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

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

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

Android官方提供的支持不同屏幕大小的全部方法


本文转载自:http://blog.csdn.net/guolin_blog/article/details/8830286

共有 人打赏支持
jdroid
粉丝 16
博文 84
码字总数 23247
作品 0
海淀
加载中

评论(1)

suzhenwin
suzhenwin
已经转行iOS和安卓很少碰了,可惜了很有前途的一个手机操作系统,似乎有点毁在一群厂商的大屏幕竞赛里的味道
android分辨率(屏幕适配)

关于手机分辨率相关术语和概念 屏幕尺寸:实际的物理尺寸,屏幕的对角线测量。为了方便,android把所有的屏幕尺寸分为了4个广义的大小:小,正常,大,特大。 屏幕密度:屏幕的物理面积内像素...

带梦想一7飞
2013/05/31
0
1
Android官方提供的支持不同屏幕大小的全部方法

本文将告诉你如何让你的应用程序支持各种不同屏幕大小,主要通过以下几种办法: 让你的布局能充分的自适应屏幕 根据屏幕的配置来加载合适的UI布局 确保正确的布局应用在正确的设备屏幕上 提供...

带梦想一7飞
2013/06/05
0
0
android系统如何自适应屏幕大小

1、屏幕相关概念 1.1分辨率 是指屏幕上有横竖各有多少个像素 1.2屏幕尺寸 指的是手机实际的物理尺寸,比如常用的2.8英寸,3.2英寸,3.5英寸,3.7英寸 android将屏幕大小分为四个级别(small...

mfcai
2013/01/27
0
0
Android 屏幕自适应问题

Android9 patch 图片 (.9.png 格式图片) 的特点和制作 一.9.png格式的文件的特点 与传统的png 格式图片相比, 9.png 格式图片在图片四周有一圈一个像素点组成的边沿,该边沿用于对图片的可扩...

ljrapple
2015/03/02
0
0
Android应用屏幕适应问题的解决

1、android多屏幕支持机制 Android的支持多屏幕机制即用为当前设备屏幕提供一种合适的方式来共同管理并解析应用资源。 Android平台中支持一系列你所提供的指定大小(size-specific),指定密度...

Android1989
2014/07/30
0
0
Android 自适应不同分辨率屏幕

前几天,面试的时候,有问道关于如何自适应不同分辨率屏幕的问题。当时也是一知半解,今天索性看了很多资料,好好的总结了下。 首先解释几个基本的概念: in:表示英寸,是屏幕的物理尺寸。每...

的书法上的
2014/07/15
0
0
基于Android平台的多分辨率解决方案[图]

摘要:近年来,智能手机的功能越来越强大,移动终端应用程序层出不穷,移动互联网改变人们的生活。Android系统是开放手机联盟推出的一款开源的手机操作系统,正是由于其开放性,没有采用Windows P...

笨笨熊的徒弟
2012/11/12
0
0
创建灵活的用户界面-Android Fragment

创建灵活的用户界面-android Fragment. Android Support Library(支持库)提供了包含一个API库的JAR文件,当你的应用运行在Android早期版本时,Support Library(支持库)允许你的应用使用最近版...

顶层设计
2013/02/26
0
0
android获取屏幕尺寸与密度

    遇到一个问题,我的地图浮标图片在WVGA手机上正好,在QVGA上就显的太大,所以我要根据屏幕的不同调整浮标的大小使其在QVGA大小合适。有的同事提出了依据分辨率来区分不同的屏幕,但是...

rainy86
2014/07/09
0
0
Android度量单位说明(DIP,DP,PX,SP)

(一)概念 dip: device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA 推荐使用这个,不依赖像素。 px: pixels(像素...

sflfqx
2014/12/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

shell中的函数、shell中的数组、告警系统需求分析

shell中的函数 格式: 格式: function f_name() { command } 函数必须要放在最前面 示例1(用来打印参数) 示例2(用于定义加法) 示例3(用于显示IP) shell中的数组 shell中的数组1 定义数...

Zhouliang6
39分钟前
1
0
用 Scikit-Learn 和 Pandas 学习线性回归

      对于想深入了解线性回归的童鞋,这里给出一个完整的例子,详细学完这个例子,对用scikit-learn来运行线性回归,评估模型不会有什么问题了。 1. 获取数据,定义问题     没有...

wangxuwei
今天
0
0
MAC安装MAVEN

一:下载maven压缩包(Zip或tar可选),解压压缩包 二:打开终端输入:vim ~/.bash_profile(如果找不到该文件新建一个:touch ./bash_profile) 三:输入i 四:输入maven环境变量配置 MAVEN_HO...

WALK_MAN
今天
0
0
33.iptables备份与恢复 firewalld的9个zone以及操作 service的操作

10.19 iptables规则备份和恢复 10.20 firewalld的9个zone 10.21 firewalld关于zone的操作 10.22 firewalld关于service的操作 10.19 iptables规则备份和恢复: ~1. 保存和备份iptables规则 ~2...

王鑫linux
今天
1
0
大数据教程(2.11):keeperalived+nginx高可用集群搭建教程

上一章节博主为大家介绍了目前大型互联网项目的系统架构体系,相信大家应该注意到其中很重要的一块知识nginx技术,在本节博主将为大家分享nginx的相关技术以及配置过程。 一、nginx相关概念 ...

em_aaron
今天
0
0
Apache Directory Studio连接Weblogic内置LDAP

OBIEE默认使用Weblogic内置LDAP管理用户及组。 要整理已存在的用户及组,此前办法是导出安全数据,文本编辑器打开认证文件,使用正则表达式获取用户及组的信息。 后来想到直接用Apache Dire...

wffger
今天
2
0
HFS

FS,它是一种上传文件的软件。 专为个人用户所设计的 HTTP 档案系统 - Http File Server,如果您觉得架设 FTP Server 太麻烦,那么这个软件可以提供您更方便的档案传输系统,下载后无须安装,...

garkey
今天
1
0
Java IO类库之BufferedInputStream

一、BufferedInputStream介绍 /** * A <code>BufferedInputStream</code> adds * functionality to another input stream-namely, * the ability to buffer the input and to * sup......

老韭菜
今天
0
0
STM 32 窗口看门狗

http://bbs.elecfans.com/jishu_805708_1_1.html https://blog.csdn.net/a1985831055/article/details/77404131...

whoisliang
昨天
0
0
Dubbo解析(六)-服务调用

当dubbo消费方和提供方都发布和引用完成后,第四步就是消费方调用提供方。 还是以dubbo的DemoService举例 -- 提供方<dubbo:application name="demo-provider"/><dubbo:registry address="z...

青离
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部