为什么要进行屏幕适配、对哪些设备进行适配?
在近几年的发展当中,安卓设备数量逐渐增长,由于安卓设备的开放性,导致安卓设备的屏幕尺寸大小碎片化极为严重。

【友盟+】2016年手机生态发展报告H1中看截止16年手机分辨率使用情况:Android设备720p和1080p是主流,如果对前5中Android设备分辨率进行适配就能让app在90%的安卓设备上比较美观的兼容。

涉及重要概念及关系

1.硬件属性 ── 屏幕尺寸、屏幕分辨率、屏幕像素密度

【屏幕尺寸】:屏幕对角线长度。单位是英寸,1英寸=2.54厘米。
【屏幕分辨率】:屏幕横纵向上的像素点数。单位是px,1px=1像素点。
【像素密度】:屏幕每英寸上的像素点数,单位是dpi,即dot per inch缩写。
【关系及总结】:屏幕同尺寸分辨率越高(像素点越多),像素密度越大,显示效果越好。
像素密度=横向像素点数^2+纵向像素点数^2然后开方取得值,除以屏幕尺寸。
【举例】:【Nexus 5 :4.95英寸、1920*1080、445dpi】
445dpi=(√(1080^2+1920^2))px/4.95 inch

2.计量单位 ── dp、dip、dpi、sp、px。

【dpi】:屏幕每英寸上的像素点数,单位是dpi,即dot per inch缩写。
【px】:像素,构成图像的最小单位。(进行ui设计、官方原生api返回的数值都是以px作为计量单位的,比如获取屏幕的宽和高。)
【dp、dip】:密度无关像素。即Density Independent Pixels缩写。(dp等同于dip,以160dpi为基准,1dp=1px。dp意义在于:你可以根据看到的实际大小,在应用中设置对应的dp值,而使得不同的设备上看起来一样大。)
【sp】:即Scale-Independent Pixels。可以根据文字大小首选项进行缩放。推荐使用12sp以上大小的文字;推荐使用12sp、14sp、18sp、22sp;字体大小不要使用奇数和小数,在字体放缩的时候可能导致精度的丢失。
【举例】:

3.像素密度 ── mdpi、hdpi、xhdpi、xxhdpi、xxxhdpi。

不同的设备上实现非常好的显示效果,因此有多种像素密,主流的5种像素:mdpi、hdpi、xhdpi、xxhdpi、xxxhdpi,以2:3:4:6:8的比例缩放,可修饰drawable和values。

AndroidManifest.xml设置在中Menifest中添加子元素android:anyDensity=”true”时,应用程序安装在不同密度的终端上时,程序会分别加载xxhdpi、xhdpi、hdpi、mdpi、ldpi文件夹中的资源。相反,如果设为false,即使在文件夹下拥有相同资源,应用不会自动地去相应文件夹下寻找资源。

解决方案及布局优化适配各种屏幕尺寸

(I)线性布局中使用:wrap_content、match_parent、weight属性。

在设置控件长宽的时候一般有三种方案:
1.直接用dp属性将控件写死。
2.wrap_content内容自适应。
3.match_parent填充父布局。
以下如图为使用wrap_content、match_parent、weight属性实现的小例子:
用weight属性将tittle栏中间控件进行拉伸适配,左右控件大小不变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="左侧控件" />
<TextView
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="25sp"
android:background="#f5f5f5"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="右侧控件 右侧控件" />
</LinearLayout>

[weight属性扩展]
将一排所有控件都加上权重比例时,此时可以将宽度 wrap_content 改为0dp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="左侧控件"
/>
<Button
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="右侧控件" />
</LinearLayout>


若将layout_width属性设为match_parent的话,比例将会颠倒。

[原因]
weight等式为:
weight计算出的宽度=原来的宽度+屏幕剩余控件宽度所占的百分比
[解释]
假设屏幕宽度为L
则左侧控件宽度=L(match_parent)+[L-2L(两个控件总宽)]1/3=2/3L
同理右侧控件宽度=L(match_parent)+[L-2L(两个控件总宽)]
2/3=1/3L
为了证明等式成立,将宽度改为0dp再算一次
则左侧控件宽度=0dp+[L-0-0]1/3=1/3L
则左侧控件宽度=0dp+[L-0-0]
2/3=2/3L

(II)使用相对布局、禁用绝对布局。

绝对布局以一坐标的方式来定位在屏幕上的位置,此布局难维护,一旦屏幕分辨率发生变化,
由于相对位置绝对性,控件将不会自动适配宽高,如图。

线性布局优势可以用weight去适配屏幕的比例大小,但是一些比较复杂的布局,线性布局使用起来就比较麻烦,
这个时候我们可以使用相对布局来适配优化,如图为官方demo,第二排的ok按钮,我们只需要让它紧贴父布局右侧。
Cancel按钮只需位于OK按钮左侧。(若用线性布局去实现,则至少需要两次嵌套。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/edit" />
<Button
android:layout_alignParentRight="true"
android:layout_below="@id/edit"
android:text="OK"
android:layout_width=&#34 大专栏  Android实习生 —— 屏幕适配及布局优化;wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button2" />
<Button
android:layout_toLeftOf="@id/button2"
android:layout_below="@id/edit"
android:text="CANCEL"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button3" />
</RelativeLayout>

(III)使用限定符适配平板设备:large限定符、最小限定符、方向限定符。

[使用large限定符]分别创建layout/main.xml,layout-large/main.xml下的不同布局,以适配手机和平板。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//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"
aandroid:layout_width="match_parent" />
</LinearLayout>
//res/layout-large/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.bb.HeadlinesFragment"
android:layout_width="400dp"
android:layout_marginRight="10dp"/>
<fragment android:id="@+id/article"
android:layout_height="fill_parent"
android:name="com.bb.ArticleFragment"
android:layout_width="fill_parent" />
</LinearLayout>

注意large限定符是在安卓3.2版本以前版本才会起作用的!3.2之后,为了能更精确判断平板范围,谷歌推出了[最小宽度限定符]。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//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.bb.HeadlinesFragment"
android:layout_width="match_parent" />
</LinearLayout>
//res/layout-sw600dp/main.xml,双面板布局: Small Width 最小宽度
<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.bb.HeadlinesFragment"
android:layout_width="400dp"
android:layout_marginRight="10dp"/>
<fragment android:id="@+id/article"
android:layout_height="fill_parent"
android:name="com.bb.ArticleFragment"
android:layout_width="fill_parent" />
</LinearLayout>

通过以上,想要兼容安卓3.2之前的平板设备,需要设置添加这三种lyout。
res/layout/main.xml: 单面板布局
res/layout-large/main.xml: 多面板布局
res/layout-sw600dp/main.xml: 多面板布局
这样维护起来比较困难,如改变large面板布局,还要去更改sw600dp 面板。
我们引入[布局别名]:将多面板相同的地方抽取出来设为main_twopanes进行统一的管理。
res/layout/main.xml 单面板布局
res/layout/main_twopanes.xml 双面板布局
所以我们这么来操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
setContentView(R.layout.custom-main);
默认布局
res/values/layout.xml:
<resources>
<item name="custom-main" type="layout">@layout/main</item>
</resources>
Android3.2之前的平板布局
res/values-large/layout.xml:
<resources>
<item name="custom-main" type="layout">@layout/main_twopanes</item>
</resources>
Android3.2之后的平板布局
res/values-sw600dp/layout.xml:
<resources>
<item name="custom-main" type="layout">@layout/main_twopanes</item>
</resources>
1
2
3
4
5
6
7
8
9
10
11
最后一种限定符:[方向限定符]
//平板横向
res/values-sw600dp-land/layouts.xml:
<resources>
<item name="custom-main" type="layout">@layout/main_twopanes</item>
</resources>
//平板竖直
res/values-sw600dp-port/layouts.xml:
<resources>
<item name="custom-main" type="layout">@layout/main</item>
</resources>

(IV)使用自动拉伸位图——消息气泡框

在Android的设计过程中,为了适配不同的手机分辨率,图片大多需要拉伸或者压缩,这样就出现了可以
任意调整大小的一种图片格式“.9.png”。这种图片是用于Android开发的一种特殊的图片格式,它的好处
在于可以用简单的方式把一张图片中哪些区域可以拉伸,哪些区域不可以拉伸设定好,同时可以把显示内容
区域的位置标示清楚。

我们可以明显看到.9.png的外围是有一些黑色的线条的1、2、3、4,它们的作用及说明:
序号1和2标识了可以拉伸的区域。(如图只可拉伸标记的一个像素点。)
序号3和4标识了内容区域。

整理作者:汪博
个人名言:少壮不努力,老大徒悲伤。

Android实习生 —— 屏幕适配及布局优化的更多相关文章

  1. Android UI学习 - FrameLayou和布局优化(viewstub)

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://android.blog.51cto.com/268543/308090 Fram ...

  2. Android 多屏幕适配 dp和px的关系 最好用dp

    Android 多屏幕适配 dp和px的关系 一直以来别人经常问我,android的多屏幕适配到底是怎么弄,我也不知道如何讲解清楚,或许自己也是挺迷糊. 以下得出的结论主要是结合官方文档进行分析的ht ...

  3. Android开发——Android手机屏幕适配方案总结

    )密度无关像素,单位为dp,是Android特有的单位 Android开发时通常使用dp而不是px单位设置图片大小,因为它可以保证在不同屏幕像素密度的设备上显示相同的效果. /** * dp与px的转 ...

  4. Android各种屏幕适配原理

    dip(dp): device independent pixels(设备独立像素) dip,就是把屏幕的高分成480分,宽分成320分.比如你做一条160dip的横线,无论你在320还480的模拟器 ...

  5. android 多屏幕适配 : 第一部分

    1.在xml布局文件中,控件的宽度和高度用  dp ;   字体大小用 sp 2.根据屏幕的宽高来动态的适配 , 获取屏幕的宽高的两种方法: 第一种方法: /** * 屏幕的宽度 * 屏幕的高度 * ...

  6. Android 关于屏幕适配

    android屏幕适配详解 官方地址:http://developer.android.com/guide/practices/screens_support.html 转自:http://www.c ...

  7. [转]android – 多屏幕适配相关

    1.基本概念 屏幕大小(screen size) – 屏幕的实际大小,用屏幕对角线长度来衡量(比如3.4寸,3.8寸).android把屏幕分为以下4种:small,normal,large,extr ...

  8. Android 多屏幕适配 dp和px的关系

    一直以来别人经常问我,android的多屏幕适配到底是怎么弄,我也不知道如何讲解清楚,或许自己也是挺迷糊. 以下得出的结论主要是结合官方文档进行分析的https://developer.android ...

  9. 最清晰的Android多屏幕适配方案

    问题的引入 当您的Android应用即将发布的时候,如果你想让更多的用户去使用你的应用,摆在工程师面前的一个重要问题就是如何让你的应用能在各种各样的终端上运行,这里的各种各样首当其冲的就是不同的屏幕分 ...

随机推荐

  1. tensorflow中使用指定的GPU及GPU显存

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本文目录 1 终端执行程序时设置使用的GPU 2 python代码中设置使用的GPU 3 设置tensorflow使用的显 ...

  2. NSPredicate 应用1

    //查找名字里面包含“王”的姓 NSArray *array = [[NSArray alloc]initWithObjects:@"小王",@"王力",@&q ...

  3. 吴裕雄--天生自然 PYTHON3开发学习:多线程

    import _thread import time # 为线程定义一个函数 def print_time( threadName, delay): count = 0 while count < ...

  4. set_include_path详细解释(转)

    首先我们来看这个全局变量:__FILE__它表示文件的完整路径(当然包括文件名在内)也就是说它根据你文件所在的目录不同,有着不同的值:当然,当它用在包行文件中的时候,它的值是包含的路径: 然后:我们看 ...

  5. Perl:正则中问号的四周用途:1.字面意义的问号 2. 量词 3. 表示非贪心的修饰符 4.用以表示不具有记忆功能的圆括号

    Perl:正则中问号的四周用途:1.字面意义的问号  2. 量词   3. 表示非贪心的修饰符  4.用以表示不具有记忆功能的圆括号 非贪心:在量词后面加?即可

  6. MRP运算报错-清除预留

    MRP运算报错-清除预留

  7. 54)PHP,访问修饰符

    类外就是你再实例化成对象的时候  用你类里面的变量 继承的类内,  就是子类里面,但是实例化对象时,不能用 本类内,      只在本类的定义时用,子类不能用.

  8. B. Split a Number(字符串加法)

    Dima worked all day and wrote down on a long paper strip his favorite number nn consisting of ll dig ...

  9. F. Wi-Fi(线段树实现dp)

    题:http://codeforces.com/contest/1216/problem/F dp[i][0]:表示第i个位置不装的最小代价 dp[i][1]:表示第i个位置装的最小代价 T1的线段树 ...

  10. Qt LNK1112: 模块计算机类型“x64”与目标计算机类型“X86”冲突问题

    解决方法:1.找到选项: 2.点击构建套件kit,选择x86_amd64,之后便不会出现类似问题了