Android 之UI自适应解决方式

1.概况

       作为Android开发者,最头疼的莫过于让自己开发的程序在不同终端上面的显示效果看起来尽量一致(当然。假设要充分利用大屏幕的优势另当别论)。在全球范围内来讲。android有着数以亿计的设备,当中就不乏设备分辨率多种多样。以及设备屏幕物理尺寸的多样化。

         总得来说我们须要做的有三点。其一让APP的每一个UI中的每一个View宽和高更加灵活以适应不同分辨率、其二对于大屏幕设备(PAD)须要有不同的设计,竟可能多的展示内容。获取你整个APP的全部UI都能够做到一个布局中来、其三图标资源需提供不同尺寸(MDPI、HDPI、XHDPI、XXHDPI、XXXHDPI),你也能够图方便仅仅提供一套较高尺寸的API,没问题,这可能仅仅会使那些配置低的设备(或者说分辨率低,事实上实际这两者普遍成正比)耗费很多其它的内存在载入资源图片上面。

2.官方支持

 1.图标资源

官方建议APP中使用的图标资源都需提供drawable-ldpi(眼下来看,已经没有必要)、drawable-mdpi、drawable-hdpi、drawable-xhdpi。

说到DPI(Dots Per Inch)事实上就是单位尺寸有多少个像素,计算方式就是手机分辨率宽的平方+高的平方,再开根号得到斜对角线分辨率。

然后用这个除以屏幕的实际尺寸(也就是我们常说的4寸、5寸、7寸、10寸),这个尺寸实际也是屏幕的斜对角尺寸。这样计算出来的结果就是像素密度。像素密度越大说明手机显示越细腻。举个样例HTC One分辨率是1920*1080,屏幕尺寸是4.7英寸,拿上面的公式计算一下2202/4.7=468那么它属于上面哪个区域呢?android给出了一个范围,例如以下:


非常显然HTC One 被归入xhdpi这一类里面。

所以假设你的APP提供了drawable-xhdpi以下的图标,HTC One执行你APP时会自己选择载入那里面的。


2.布局

Android的五大布局各自是LinearLayout(线性布局)、FrameLayout(帧布局)、RelativeLayout(相对布局)、AbsoluteLayout(绝对布局)和TableLayout(表格布局)。

当中用得最多的要数LinearLayout和RelativeLayout,FrameLayout和TableLayout可在有特效需求的页面使用,这里就不介绍,而AbsoluteLayout已经被标记位Deprecated since API level 3,不建议再使用。

线性布局的特点是。里面的每一个view都是按顺序摆放,要么是垂直要么是水平,谁声明在前面谁显示时就排在前面。

而相对布局位置不受排放顺序的限制,能够在xml中指定它位于哪个view的上方、下方、左边或右边。

做自适应最关键的地方就在布局上面,首先拿到需求后分析页面採用何种布局结构才干更好的做到自适应,或者APP设计时就设计得比較简单,而手机端软件的设计规则也是越简单越好用!在布局上尽量使用match_parent个wrap_content,绝对不要使用px(当然假设你的APK仅仅须要支持某一种分辨率除外),非要设置详细大小时使用dp做单位,这样才干在不同DPI但物理尺寸大小一样的手机上面通用。

但都用dp并不能满足同一时候适应手机和平板(物理尺寸存在较大差异)。由于平板的物理尺寸比較大一般是7寸以上。举个样例。两个Button将其大小设置为width 50dp height 50dp,它在800*480 尺寸为4寸的手机上面显示效果例如以下:

 

而在1024*600的七寸平板上面显示效果例如以下:

 

 

非常显然在平板上面显示效果感觉太小了。为什么会出现如此差异,我们能够通过计算得出答案。800*400 4寸 DPI是230。normal状态下DPI是160,据此我们能够算出50dp在这个800*480 4寸设备上面占用的像素是230/160*50 = 72px ,显然这个宽度仅仅占到整个屏幕宽度的72/480=0.15。再看看截图,应该几乎相同是这么个比例吧。假设是在1024*600的7寸(DPI是170)设备上面50dp占用的像素是170/160*50=53px,这样整个button占领屏幕的宽度就仅仅有53/600=0.09,也就是如截图看到的一样占用非常小的一坨。

所以,通过dp作为单位不能解决不同尺寸设备的自适应问题,相同android也提供了对应的解决的方法,在android3.2 (API 13)曾经对屏幕大小做了例如以下分类:


要想在布局文件里区分不同尺寸设备能够通过layout-small、layout-normal、layout-large和layout-xlarge,依据我们刚才计算的值,仅仅需在layout-large中指定button的大小为x这个x的值能够通过公式算出来x*(170/160)/600=0.15  x = 600*0.15/(170/160)=95dp,再看下效果例如以下:

 

这样就它们显示起来的效果就差点儿一样了。同一时候,不光是大小,显示的位置都能够依据屏幕的大小做不同的显示。普通情况下你须要维护layout layout-large和layout-xlarge三套布局文件,在android 3.2以后官方又提供了更加精确的尺寸大小区分办法。sw<N>dp,当中sw指的是长和宽中的较小者。比方1024*600的7寸,sw的计算方式是600/(170/160)=565dp,但实际是不正确的,參考网页《官方六》中的描写叙述:

Note: The sizes that you specify using thesequalifiers are not the actual screen sizes. Rather, the sizes arefor the width or height in dp units that are available to youractivity's window. The Android system might use some of the screen forsystem UI (such as the system bar at the bottom of the screen or the status barat the top), so some of the screen might not be available for your layout.Thus, the sizes you declare should be specifically about the sizes needed byyour activity—the system accounts for any space used by system UI whendeclaring how much space it provides for your layout. Also beware thatthe Action Bar isconsidered a part of your application's window space, although your layout doesnot declare it, so it reduces the space available for your layout and you mustaccount for it in your design.

所以说须要注意的是计算sw时会有一定得区间浮动,我们须要尽量定义小些。比方565dp假设你定义为sw565dp。但实际是sw564dp,那么就不会走到sw565dp里面去了。而是採用向下找近期的原则,假设都没找到就使用默认的layout。

       对于官方为什么会引入sw这个概念,是由于large xlarge已经不能适应各种厂商太多的中间尺寸,比方5.5 、5.7、 6 、 6.5等等,假设是android3.2下面。这些将所有被归入large的范畴。这种话5.5和7寸设备显示的效果就会有些出入,当然不会有非常大出入。

为了满足人们对设计的精益求精,在android3.2以后的设备中都能够使用sw来做更细的划分。如sw480dp sw600dp sw720dw sw1024dp等等。

      当然为了避免维护如此多的layout布局文件我们还能够用另外的版本号来完毕自适应的动作。如上面的样例,每一个button都是占屏幕宽度的0.15,我们能够用layout_weight权重这一概念,设置该button的权重为0.15就可以,它就会在每一个设备上面达到相同的效果—均占屏幕宽度的0.15,高也是同理。对与宽高比例一致的设备这是一个不错的选择,但对与不同宽高比的设备,全然使用layout_weight来做自适应显然是不能达到效果的,比方800*480和854*480的设备,假设高採用相同的weight,854的高肯定会显得拉伸。假设button上面有背景图片。则图片会变形。

有一个小技巧能够解决此问题。就是用ImageView来取代Button,同一时候将背景图片设置为android:src。曾经景的模式显示。这样能够利用imageview的属性,使图片保持原始的比例填充。

     

3.数值

布局文件里会用到各种数值。如view的宽、高,字体的大小padding大小,magin大小等均能够在values目录中定义当中就包含strings.xml dimens.xml styles.xmlcolor.xml等等,当然跟自适应相关的就是dimens.xml。这里面定义了各种view属性的大小,比如button的高为50dp能够在dimens里面定义<dimen name="btn_size">50dp</dimen>然后将button的android:layout_width="@dimen/btn_size "。在布局部分我们讲到用layout-large layout-sw600dp等来区分不同屏幕大小的设备,相同在values里面也能够加上values-largevalues-sw600dp等来区分。比方最開始的样例里面我们能够仅仅定义一个layout 将button的宽高都设置为@dimen/ btn_size,然后定义一个values/dimen.xml 和一个values-large/dimen.xml,分别写上<dimen name="btn_size">50dp</dimen>和<dimen name="btn_size">95dp</dimen>,这和写多个layout效果是一样的。但我个人认为假设页面相对照较简单。在values里面下功夫比写多个layout要简单些。

3. 扩展

有时我们APP须要支持到比較旧的API版本号。但我们有想用到一些比較高级的API里面的功能,这时我们能够在values后面加上-v<xx>如values-v11。当中11就是API版本号,也就是11以上API的设备就会採用values-v11里面的内容。就比方API 11里面增加了Action Bar的功能。那么假设你想利用这个特性,能够在values-v11里面定义一个style.xml,继承自action bar相关的style,而在values里面的style.xml中定义不支持action bar的style。但在布局中用其它view来模拟action bar的效果。

4.总结

对与UI自适应总结一下主要是两点。同样屏幕尺寸不同分辨率以及不同屏幕尺寸同样分辨率。对于前者,仅仅需在布局中用到单位的地方所实用dp就可以解决(有条件的话drawable最好能提供不同分辨率icon,实在不行。提供同意范围内尽量大分辨率图片)。对于后者,则须要依据尺寸的等级写不同的layout文件或者values文件。这个需依据项目的详细负责程度来自由选择。

原文地址:https://www.cnblogs.com/yxysuanfa/p/6803184.html