Android 屏幕适配
发布时间:2025-05-13 02:28:19 发布人:远客网络
一、Android 屏幕适配
摘自:
摘自:
摘自:
因为ui设计师给你的设计图是以px为单位的,Android开发则是使用dp作为单位的,那么我们需要进行转换:
Android推荐使用dp作为尺寸单位来适配UI,通过dp加上自适应布局和weight比例布局可以基本解决不同手机上适配的问题,这基本是最原始的Android适配方案。
(1)这种方案只能保证我们写出来的界面适配绝大部分手机,部分手机仍然需要单独适配,但dpi的不同,还是会存在差异。
(2)一般的设计稿都是以px为单位的,所以我们在写layout文件的时候需要将px转为dp,影响开发效率。
为了高效的实现UI开发,出现了新的适配方案,我把它称作宽高限定符适配。简单说,就是模仿市面上所有的Android手机的宽高像素值,设定一个基准的分辨率,其他分辨率都根据这个基准分辨率来计算,在不同的尺寸文件夹内部,根据该尺寸编写对应的dimens文件:
鸿洋大神的作品,使用也超级简单,核心功能就是在绘制的时候在onMeasure里面做变换,重新计算px。
我们自定义的控件可能会被影响或限制,可能有些特定的控件(框架没有做适配的控件),需要单独适配。
小结:上述几种适配方案都是实际开发中用过的方案,但随着技术不断的更新,出现了更好的适配方案。
1.SmallestWidth适配(sw限定符适配)
Android会识别屏幕可用高度和宽度的最小尺寸的dp值(其实就是手机的宽度值),然后根据识别到的结果去资源文件中寻找对应限定符的文件夹下的资源文件。
sw限定符适配和宽高限定符适配类似,区别在于,前者有很好的容错机制,如果没有value-sw360dp文件夹,系统会向下寻找,比如离360dp最近的只有value-sw350dp,那么Android就会选择value-sw350dp文件夹下面的资源文件。这个特性就完美的解决了上文提到的宽高限定符的容错问
1.非常稳定,极低概率出现意外
2.不会有任何性能的损耗
3.适配范围可自由控制,不会影响其他三方库
就是多个dimens文件可能导致apk变大,几百k。
这里有个问题:
在项目的其他 module中怎么实现适配?难道也要多套 dimens文件?
解答:
并不需要多套 dimens文件,只需要在 values文件夹下有一套与 app module一样的 dimens文件即可达到适配。因为经过编译,所有 module中的 dimen数据都会统一归类到主 module(即 app module)中的 values/dimens.xml文件中了,然后系统又会根据你设置的值去找对应 values-swxxxdp文件夹下的dimens.xml文件中的值。
附件: [生成sw文件的工具]( ?
to=https%3A%2F%2Fgithub.com%2Fladingwu%2Fdimens_sw)
实现原理:修改系统的density值(核心)
今日头条适配是以设计图的宽或高进行适配的,适配最终是改变系统density实现的。
1.只需要修改一次 density,项目中的所有地方都会自动适配,这个看似解放了双手,减少了很多操作,但是实际上反应了一个缺点,那就是只能一刀切的将整个项目进行适配,但适配范围是不可控的。
2.这个方案依赖于设计图尺寸,但是项目中的系统控件、三方库控件、等非我们项目自身设计的控件,它们的设计图尺寸并不会和我们项目自身的设
AndroidAutoSize是基于今日头条适配方案,该开源库已经很大程度上解决了今日头条适配方案的两个缺点,可以对activity,fragment进行取消适配。也是目前我的项目中所使用的适配方案。
使用也非常简单只需两步:
第一步:导入依赖
第二步:配置AndroidManifest
在 AndroidManifest中填写全局设计图尺寸(单位 dp),如果使用副单位,则可以直接填写像素尺寸,不需要再将像素转化为 dp,详情请查看 demo-subunits
老师给的UI设计是在蓝湖上的,因为还没工作,接触就蓝湖,SW个人感觉好处就是蓝湖上尺寸多少你就写多少就行
二、关于Android界面适配的思考及最终解决方案
1、一直以来都用 px映射表来解决不同界面的适配性问题(参考: Android界面开发精要1:尺寸)。最近在一些设备上发现,这种方案也有弊端:以UI图的基础设计是基于720*1280(如Galaxy Nexus)为例,最近发现有些设备的像素宽高比并不是如此,比如Nexus 4就是768*1280。
2、这种情形下,不同的映射方式会有不同的效果:
3、仔细思考就会发现问题的本质是:控件宽高计算基准是不同的。
4、这让我想起iOS开发中,其界面设计系统AutoLayout,就采用了一个计算公式:
5、也就是说,任何控件都可以以其他控件的属性值来定义自身的属性值,所以其可塑性非常高。不过实际应用中也会带来一个问题,就是太灵活,导致多重约束,有时候会彼此冲突。
6、仔细想想,最常见的视角参数应该就只有3个:
7、透过这3个参数,应该可以定义任意控件的属性值。
8、现在问题来了,Android怎么做到呢?答案是:**** android-percent-support-extend****
9、对于值可以取:10%w, 10%h, 10%, 10%sw, 10%sh,缩写含义为
10、对于一开始的界面,最后xml文件为:
11、这种直接裸写百分比的方式比价繁琐,相较之下,目前采用 px映射表的方案中写的px值直接在UI设计图中取就行,更加简单。
12、其实px映射表方案也就是百分比的方案,而且x值和y值已经分开,所以也可以解决正方形变形的问题。
13、目前需要客服的问题主要在于px映射为px,导致如果没有覆盖到设备的分辨率,就会出现问题,改成px映射为dp后,这种问题应该会减少很多。
三、android屏幕适配问题
这里我们引入 ppi(pixel per inch)名词,翻译过来就是每英寸的距离像素点的个数。现在来解释上面的现象。对于一张200x200像素的图片,我国我们想要显示在 200ppi的手机上,那么占用屏幕的长和宽均为 200pix/(200pix/ inch)= 1 inch,也就是说要占用 1 inch x 1 inch,如果要显示在 300ppi的手机上,那么占用屏幕的长和宽均为 200pix/(300pix/ inch)= 2/3 inch,也就是说对于 ppi越高的手机,单位inch上能够显示更多的像素点,因此当这两种手机显示同样多的像素点的时候,ppi越高的手机占用的空间就越小。这就是我们想要图片在各种手机屏幕上都显示一致的效果时需要解决的问题。
既然这种效果不是我们想要的,怎么做才能获取一致的显示效果呢?下面介绍三种方法
方法一:对每一中不同的ppi使用不同的图片,这需要我们先判断屏幕的ppi,再对图片进行处理,然后显示,显然比较麻烦。而且对于获取屏幕ppi这个参数android并没有提供给我们api调用。所以这种办法基本行不通
方法二:在用eclipse开发环境生成一个android项目后,系统会给我们生成drawable-ldpi、drawable-mdpi、drawable-hdpi、drawable-xhdpi,drawable-xxhdpi,对于同一张图片资源,我们分别创建这五个版本来适应不同的屏幕。假设你想一张图片
在 200ppi和400ppi的手机上显示的长和宽都是一样的为 1inch x 1inch,那么你就需要制作一张200x200的图片和一张
400x400的图片,然后放入对应得drawable目录中就可以了。那么程序运行时怎么知道自己到底是使用哪个drawable目录下
的图片呢?这个是不需要我们考虑的,而是手机厂商考虑的问题,只需要知道,程序会使用适应当前屏幕的目录下的图片
drawable-ldpi、drawable-mdpi、drawable-hdpi、drawable-xhdpi,drawable-xxhdpi,这几个目录对应的pppi为
120ppi 160ppi 240ppi 320ppi 480ppi,也就是说如果屏幕的ppi为320,那么就会优先使用drawable-xhdpi目录下的
图片资源。当然手机屏幕的ppi也是多种多样,例如有的是 300ppi,有的是220ppi,这个系统会选择最接近的目录,也就
是 300ppi的手机会选择320ppi对应的drawable目录下的资源
方法三:方法2中需要为每个drawable目录都生成对应的图片版本,如果图片较多的话,生成不同版本的图片倒是小事更主要的缺点是会增大应用的大小,那么可不可以只在一个目录下存放图片,例如只在drawable-mdpi目录下存放图片呢答案是可以的,假设我们在drawable-hdpi(对应的ppi为160ppi)目录下存放了一个100X100的图片,那么当图片需要
在320ppi的android设备上进行显示时,android系统会将自动将图片进行处理生成一个200X200的图片显示到设备上,那么他们占用的空间大小分别为 100/160= 3/5 inch 200/320= 3/5 inch可以看出他们占用的长和宽都是一样的这种自动缩放的优点是只需要一张图片就能适应各种ppi类型的屏幕。缺点是当对100X100的图片进行变换成200X200的图片时肯能会造成图片的不清晰,如果提供一个drawable-xhdpi下的图片资源,图片较多的话会无形增加应用的大小,所以说如何进行选择也是一个衡量。建议是将比较重要的图片资源提供多个版本(当android设备和自己的ppi相对应的drawable下找到想要的资源时,就不会再到其他目录需找资源)。不是很重要的图片资源存储一个版本,让系统根据自己的ppi自己对图片进行适当的缩放显示。
最后再说下为什么在布局文件中使用 dp作为单位而不是使用px
dp是一个与屏幕ppi无关的参数,同时也是一个事实上并不存在的虚拟单位。显示时会根据具体屏幕的ppi进行像素的映射,关系如下160ppi 1dp 1px120ppi 1dp 0.75px240ppi
1dp 1.5px320ppi 1dp 2px因此在布局文件中一般使用dp作为单位,这样就能适应不同ppi的屏幕,在各种ppi的屏幕上有一样大的物理上的距离。(可以看出1dp并不总是等于1px的,对于ppi高的屏幕肯能要等于2px,只是为了物理上看起来的距离是相等的)
最后希望大家能够明白我们经常说的分辨率和ppi的关系,其实他们是没多大关系。分辨率只是说明屏幕上有多少个像素点,这也跟屏幕大小有关系。当然对于屏幕大小相同的来讲分辨率越高 ppi越大,如果脱离了屏幕的物理尺寸谈分辨率是没有任何意义的。就像平板的分辨率比手机的大,那是因为平板个大呀。从颜色显示的细腻程度上讲并不见得比手机强。