Geeny 2013-06-18
对于从事android应用开发的朋友来说应该知道,现有android手机的屏幕尺寸从2.7到5.3就有二十多种。光是为了写出来的界面可以适应这么多的屏幕尺寸,就要费不少功夫!
android的屏幕类型如此繁多,大小尺寸,长宽比例都不尽相同,同一个界面在不同分辨率的手机上可能出现布局错乱,控件跑位的现象。做屏幕的适配偶们不可能实现在每种屏幕上显示出的界面效果完全一致。只能靠偶们平时的编程习惯和经验是的界面在不同的屏幕尺寸在不会出现过分的走位,在可遇见范围内控制界面在不同屏幕下的变化,并做出相应调整。
那么偶们应该如何做到屏幕的适配呢?
1,首先从布局考虑
Android的界面是由布局和组件协同完成的,布局好比是建筑里的框架,而组件则相当于建筑里的砖瓦。组件按照布局的要求依次排列,就组成了用户所看见的界面。Android的五大布局分别是LinearLayout(线性布局)、FrameLayout(单帧布局)、RelativeLayout(相对布局)、AbsoluteLayout(绝对布局)和TableLayout(表格布局)。
每种布局都有其特点,你可能会郁闷无法掌握好每种布局的使用,其实不管一个界面多复杂,偶们只需上述的一两种布局就可以实现,android提供这么多的布局供偶们选择只是为了方便偶们的开发。
本人习惯用LinearLayout,可能由于个人习惯,所以觉得线性布局的条理性更强一点,LinearLayout布局的子控件有一个很重要的属性,android:layout_weight。该属性将会在后面讲到,在这里只是建议大家选择一种自己比较熟悉的布局,自己的条理性强点,在屏幕尺寸发生变化时,能对子控件大小和位置的变化有一定的把握,这样才能做好屏幕适配。
2,px、dp和dip的关系
布局和子控件都有两个重要属性,layout_height和layout_width,用于指定控件的大小。系统还提供了几个属性供偶们使用,
1)fill_parent
设置一个构件的布局为fill_parent将强制性地使构件扩展,以填充布局单元内尽可能多的空间。这跟Windows控件的dockstyle属性大体一致。设置一个顶部布局或控件为fill_parent将强制性让它布满整个屏幕。
2) wrap_content
设置一个视图的尺寸为wrap_content将强制性地使视图扩展以显示全部内容。以TextView和ImageView控件为例,设置为wrap_content将完整显示其内部的文本和图像。布局元素将根据内容更改大小。设置一个视图的尺寸为wrap_content大体等同于设置Windows控件的Autosize属性为True。
3)match_parent
Android2.2中match_parent和fill_parent是一个意思 .两个参数意思一样,match_parent更贴切,于是从2.2开始两个词都可以用。那么如果考虑低版本的使用情况你就需要用fill_parent了。
更多情况下,为了界面可以适应不同屏幕分辨率的手机,偶们需要限制控件的大小,这里就要用到px、dp、dip、sp等等,这里只简单介绍下px和dip,其他在此不做阐述。
px: pixels(像素),不同的设备不同的显示屏显示效果是相同的,这是绝对像素,是多少就永远是多少不会改变。 显然,为了适配不同手机屏幕的显示,使用px来指定控件的大小是不行的。
dip: device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA 推荐使用这 这个,不依赖像素。
这里要特别注意dip与屏幕密度有关,而屏幕密度又与具体的硬件有关,硬件设置不正确,有可能导致dip不能正常显示。在屏幕密度为160的显示屏上,1dip=1px,有时候可能你的屏幕分辨率很大如480*800,但是屏幕密度没有正确设置比如说还是160,那么这个时候凡是使用dip的都会显示异常,基本都是显示过小。
dip的换算:
dip(value)=(int) (px(value)/1.5 + 0.5)
dp: 很简单,和dip是一样的。
所以在需要限定控件大小的时候,建议使用dip。
3、layout_weight属性
这个属性其实很好用,一般和android:layout_height="fill_parent"或android:layout_width="fill_parent"一起使用,它用于描述该子元素在剩余空间中占有的大小比例。加入一行只有一个文本框,那么它的默认值就为0,如果一行中有两个等长的文本框,那么他们的android:layout_weight值可以是同为1。如果一行中有两个不等长的文本框,那么他们的android:layout_weight值分别为1和2,那么第一个文本框将占据剩余空间的三分之二,第二个文本框将占据剩余空间中的三分之一。android:layout_weight遵循数值越小,重要度越高的原则。显示效果如下:
android屏幕如此繁多,不可能都是等比例缩放的,所以单纯使用dip来设置控件也是行不通的,与layout_weight属性灵活结合使用,增强界面的适应性。
4、drawable资源
首先:你需要在AndroidManifest.xml文件的元素如下添加子元素
1 2 3 4 5 | <supports-screens android:largeScreens="true"
android:normalScreens="true" android:anyDensity="true"
android:smallScreens="true"></supports-screens>
名如其意,以上是为我们的屏幕设置多分辨率支持(更准确的说是适配大、中、小三种密度)。android:anyDensity="true" ,这一句对整个的屏幕都起着十分重要的作用,值为true,我们的应用程序当安装在不同密度的手机上时,程序会分别加载hdpi,mdpi,ldpi文件夹中的资源。 |
相反,如果值设置为false,即使我们在hdpi,mdpi,ldpi文件夹下拥有同一种资源,那么应用也不会自动地去相应文件夹下寻找资源,这种情况都是出现在高密度,以及低密度的手机上,比如说一部240×320像素的手机,如果设置android:anyDensity="false",Android系统会将240 x 320(低密度)转换为 320×480(中密度),这样的话,应用就会在小密度手机上加载mdpi文件中的资源。
细心的人会发现自android2.0开始之后drawable文件被三个文件夹drawable-hdpi,drawable-mdpi,drawable-ldpi三个文件夹所取代,有些编程人员为了让应用程序默认地加载某些图片,他们会特意地去在android2.0之后的应用程序中重新创建drawable文件夹,其实这样做完全没有必要,通过第一段的分析我们得知,android:anyDensity="false",则应用会将大小密度转变成中密度,从而去加载mdpi中的资源。这里同样,当android:anyDensity="false",则应用会去加载mdpi中的资源。
总结一下:
第一:android:anyDensity="true",系统会依据屏幕密度,自动去找对应的文件夹
第二:android:anyDensity="false",
(1)如果drawable-hdpi,drawable-mdpi,drawable-ldpi三个文件夹中有同一张图片资源的不同密度表示,那么系统会去加载drawable_mdpi文件夹中的资源
(2)如果drawable-hpdi中有高密度图片,其它两个文件夹中没有对应图片资源,那么系统会去加载drawable-hdpi中的资源。
(3)如果drawable-hdpi,drawable-mdpi中有图片资源,drawable-ldpi中没有对应的图片资源,那么系统会加载drawable-mdpi文件夹中的资源
注意上图各种文件夹的不同表示。
drawable-hdpi 该图片即适用于横屏,也适用于竖屏
drawable-land-hdpi,当屏幕为横屏,且为高密度时,加载此文件夹中的资源
drawable-port-hdpi,当屏幕为竖屏,且为高密度时,加载此文件夹中的资源
5、draw9patch工具
android SDK包的tools目录下为偶们提供了这么一个图片处理工具。有时候偶们需要图片资源自适应且不失真,无论横屏还是竖屏,高分辨率还是低分辨率,都能自动填充满,而且不失真等等背景问题。 Android针对这种情况,专门制作了一种.9.PNG格式来解决这个问题。draw9patch就是帮助偶们制作.9.PNG格式资源的一个小工具。
*.9.PNG就标准的PNG格式,只是在最外面一圈额外增加1px的边框,这个1px的边框就是用来定义图片中可扩展的和静态不变的区域。特别说明,left(左)和top(上)边框中交叉部分是可拉伸部分,未选中部分是静态区域部分。right和bottom(下和右)边框中交叉部分则是内容部分。
如上图《也就是说,在手机里。无论上面那张图怎么放大,四周的圆角都是不会被放大的!只有left(左)和top(上)边框内才会伸缩!
在Android中以9.PNG格式的图片未背景,则能够自定义拉伸而不失真,比如系统的Button就是一个典型的例子。其实呢,无论是left和top,还是right和bottom都是把图片分成9块 (边角四块是不能缩放的,其他的四块则是允许缩放的),所以叫做9.PNG。
关于draw9patch工具的使用在此不做阐述,需要的可以参考一下博文:draw9patch教程
6、Layout资源
有时候可能由于屏幕布局过于复杂,同一个布局文件很难适应所有的屏幕分辨率。可以像drawable资源一样,在工程的res文件夹下建立多个相应的layout文件夹,为相应分辨率的屏幕编写相应的layout文件。
文件夹的命名规范是这样的:layout-分辨率
例如:layout-320x240 , layout-480x320等等。
系统就会根据运行环境的分辨率优先加载相应的文件夹下的layout布局文件。
7、代码动态添加
使用过swing的都知道如何代码动态添加控件,android也是一样的,当然代码动态添加远远没有xml布局文件方便,也不易于管理。但他的好处就是偶们可以在代码里获得运行环境的屏幕尺寸,通过计算构建相应的界面。虽然代码编写界面确实繁琐,但他的适配性也是不可否认的。
获取屏幕的大小可以有两种方法:
// 方法一:
WindowManager manager = getWindowManager();
int width = manager.getDefaultDisplay().getWidth();
int height = manager.getDefaultDisplay().getHeight();
// 方法二:
DisplayMetrics dMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dMetrics);
int screenWidth = dMetrics.widthPixels;
int screenHeight = dMetrics.heightPixels;
8、其他
除了xml文件和代码编写界面外,还可以用webview加载相应的html文件,界面内容由html完成。本人见过别人用html5编写界面也非常美观,屏幕的适应性也非常强。由于本人对html5不是很了解,在此就不细谈,有兴趣的朋友可以去了解下。
有时候可能由于屏幕实在太小,要显示的内容又实在太多,一屏实在挤不下去。可以适当的使用ScrollView控件使界面更加完整,确保用户体验。
如何将一个应用程序适配在不同的手机上,虽然这不算是一个技术问题,但是对于刚刚做屏幕的开发人员来说,还真不是一件多么简单的事情。
以上只是本人学习android开发以来的一点拙见和总结,欢迎热爱编程的朋友们一起来探讨和学习!