这里我们引入 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 075px240ppi
1dp 15px320ppi 1dp 2px因此在布局文件中一般使用dp作为单位,这样就能适应不同ppi的屏幕,在各种ppi的屏幕上有一样大的物理上的距离。(可以看出1dp并不总是等于1px的,对于ppi高的屏幕肯能要等于2px,只是为了物理上看起来的距离是相等的)
最后希望大家能够明白 我们经常说的分辨率和ppi的关系,其实他们是没多大关系。分辨率只是说明屏幕上有多少个像素点,这也跟屏幕大小有关系。当然对于屏幕大小相同的来讲 分辨率越高 ppi越大,如果脱离了屏幕的物理尺寸谈分辨率是没有任何意义的。就像平板的分辨率比手机的大,那是因为平板个大呀。从颜色显示的细腻程度上讲并不见得比手机强。
闪屏问题,可谓人神共愤。君不见,有多少人看片正要高潮,突然……
症结所在
闪屏也是常见的手机故障。究其原因,有些是因为系统设置产生的,有些是由于硬件-屏幕质量的问题。
破解之道
解决办法1:取消显示屏幕更新
如果你的手机系统是android
40以上,那么可以尝试:
设置
->
开发者选项(或者开发人员选项),将“显示屏幕更新”的勾选取消。
解决方法2:调整屏幕亮度设置
设置
->
显示
->
自动亮度调节,将这个功能关闭试试。
解决方法3:恢复出厂设置
如果上面的方法都不管用,老张也只能出最后的大招——恢复出厂设置。如果依旧不好,那么建议最好去维修一下吧。看看是不是硬件问题。
Android的最新版本会提供一些很棒的API,您的APP使用新版本API的同时也要兼容旧的Android版本,直到更多设备已更新到新版本的APP。本文档将向您展示如何利用最新的API,同时继续支持旧版本。
根据对访问Google Play商店的设备数量的统计,平台版本分布表会进行定期更新,以显示运行每个版本的Android设备的分布情况。一般来说,一个APP最好能支持大约90%的活动设备,同时使用最新的Android版本。
提示:为了在多个Android版本中提供最佳特性和功能,您应该在APP中使用Android Support Library,这样可以在旧版本上使用几种最新的平台API。
指定Minimum和Target API Levels
AndroidManifestxml文件描述APP的详细信息,并标识其支持的Android版本。具体来说,<uses-sdk>元素的minSdkVersion和targetSdkVersion属性标识了APP兼容的最低和最高API级别。
随着新版Android的发布,一些风格和行为可能会有所改变。为了让您的应用程序能够利用这些更改,并确保您的应用程序适合每个用户设备的风格,您应该把targetSdkVersion的值设置为最新的Android版本。
在运行时检查系统版本
Android在Build常量类中为每个平台版本提供了一个唯一的编码。APP用这个编码来确保只有系统支持高版本API时,才会执行依赖高版本API的代码。
注意:解析XML资源时,Android会忽略当前设备不支持的XML属性。因此,您可以安全地使用仅由较新版本支持的XML属性,而不必担心旧版本遇到该代码时出错。例如,如果您设置targetSdkVersion =“11”,则APP在Android 30及更高版本上默认包含ActionBar。如果要将menu项添加到action bar,您需要在menu资源XML中设置android:showAsAction =“ifRoom”。 在跨版本的XML文件中可以安全地执行此操作,因为较旧版本的Android只会忽略showAsAction属性(即,不需要在res / menu-v11 /中添加一个单独的menu资源)。
在手机上线的情况下,在设置选项中找到更新选项,点击更新,手机会自动找到与之相应的操作系统,不是相应的系统是不会更新的,强行安装就会把手机搞成砖头。或者你到你手机相应的论坛中找到适合你手机的系统也行。但这样有点风险,主要是可能造成系统不稳定。
机型适配常见的条件无非有这三项:Android版本、屏幕分辨率、厂商机型
其中,Android版本和屏幕分辨率是Android标准的适配内容,Google提供了详细的文档。很多厂商都对系统做了不同程度的定制,可能因为各种各样的原因修改了Android系统的API,由此会带来一些兼容问题,甚至有部分机型存在一些恶心的问题。这部分通常没有文档,只能摸着石头过河。
对于这三项条件,适配原则都是性价比优先。在资源许可的条件下,为尽可能多的用户提供服务。
所以只要列出Android版本、分辨率、厂商机型的优先级,通过排列组合即可确认适配顺序和目标。
这里还有个坑,对开发者来说,厂商的出货量不重要,有多少设备联网活跃才是最核心的数据。只有联网活跃设备才可能成为用户。
Android项目的res目录下一般加上我们自己创建的,会有6个目录,分别是:drawble drawble-ldpi drawble-mdpi drawble-hdpi drawble-xhdpi drawble-xxhdpi, 这里就不包括更为特殊的drawble目录了,(比如drawlbe-land-hdpi, 表示水平方向的高分辨率的,这些都目录不管多么长,它们都是按一丁点规律匹配的, 我们的目的是, 从个别中发现规律,从而应用到整体)。
当一个apk运行起来时,Android系统会根据其所运行的手机的屏幕密度去相对应的文件夹里找指定名称的。 注意, 先去哪个目录里找,完全是根据这个手机的屏幕密度决定的。
其中注意两点:
1, 中等分辨率,即mdpi的屏幕密度是160,他是标准的参考密度。所以计算比例的时候它的比例值是1 其他屏幕密度的参考比例都是以这个为依据。
2, 默认的drawble目录(一般是自己建的),和mdpi是一样的。将放到这个目录和放到drawble-mdpi目录是一样的效果。不过一般习惯性的放一些自定义selector或者点9的在这里。
现在我们来看, HTC one V手机的屏幕密度是252ppi, 那距离哪一个最靠近呢, 就是hdpi了。 所以当apk运行在这个手机上时,首先会去这个目录找。
下面是用常见的一些类型的手机总结的一个表格:
注意一点: 上面说的对应关系,都是首选目录, 那如果首选目录里面找不到呢?
Android选择策略
上面说到, 如果屏幕所对应的文件夹没有要找的,怎么办。这是很常见的,我们开发项目时一般不会去为每一个级别的屏幕去切一套。那样做只会让apk很大。所以一般性的我们只切一两个典型密度屏幕的。但是apk是有可能会运行在从ldpi到xxhdpi的各种级别的手机上。这个时候就需要根据一定的策略去寻找了。
Android系统寻找的步骤是这样的:
1, 去屏幕密度对应的目录去找。如果找到就拿来用。
2, 如果没找到,就去比这个密度高一级的目录里面去找,如果找到就拿来用。
3, 如果没找到就继续往上找。以此类推。
4, 如果到了xxhdpi目录还没有找到的话,就会去比自身屏幕密度低一级的目录去找,如果低一级的目录>=hdpi,找到了就拿来用。
5, 如果没找到, 就去mdpi目录去找, 如果找到了,就拿来用。
6, 如果没找到,就去默认的drawble目录里去找, 如果找到了就拿来用。
7 ,如果没找到,再去最低的ldpi目录里去找。如果找到了,就拿来用。
8, 如果没找到, 那就是没找到了, 无法显示。(不过一般不会出现这种现象,因为如果每个目录都没有这个的话,你是编译不过的)
这里有两点需要注意:
① 首先会去比自己密度高的目录里去找,这是因为因为系统相信,你在密度更高的目录里会放置分辨率更大的,这样的话这个会被缩小,但同时显示效果不会有损失,但是如果优先去低一级别的目录去找的话, 找到的就会被放大,这样的话这个就会被拉扯模糊了。
eg 同一张,你在mdpi和xxhdpi目录各放了一份, 这个应用你现在运行在hdpi的手机上, 那应用会选择哪张呢。答案是xxhdpi目录里的。即便hdpi离mdpi更近一点!
②,如果在mdpi里找不到是不会直接去ldpi里找的, 而是先去默认的drawble目录里找,这是drawble目录和drawble-mdpi是一个级别的。
下面用一张流程图来总结:
(注: 以上流程图是我通过做实验总结出来的,如有谬误还望指出。)
Android系统对的缩放规则
上文中提到如果在手机对应的目录没有找到,就会按照一定的策略去其他目录找,那找到了以后就原图显示么? 非也。
对于放在不同目录下的, 系统会按照一定比例对原始的进行放大或者缩小, 具体的放大缩小比例可参考下表, 所在目录和对应的屏幕密度是相同时缩放比例为1,也就是原图显示,而横向的比例表示分别放在该密度手机上运行时被缩放的比例。
对原始的缩放倍数。
上表几点值得注意的地方:
①, drawable目录和drawable-mdpi目录和dp到px的转换关系是一样的。
②,当你放一个120px180px的到drawable-hdpi目录,如果此应用运行在一个xhdpi的手机上,则这个会被拉扯到160px240px。
③, 最后一行dp->px, 说明了在代码或者布局文件中声明一个dp值, 这个值在不同屏幕密度的手机中会被乘以不同的倍数。 比如你在布局文件中写了一个宽和高分别为120dp和180dp的LinearLayout, 那么当这个应用运行在xhdpi的手机上时(比如上面那个常见手机表中的中兴U985手机),它的实际像素就会被转换为240px360px。 如果运行在ldpi的手机上,就变成了90px135px。 但是在这两个手机中显示的区域大小从肉眼看,是一模一样大的。(这点作为后面内容的一个引子,“看起来”一样大,这就是Android的一个神奇的地方)
我们来做个试验
试验材料:
① 一张120px180px的
② 四部手机, 具体参数参考上面的一张表格。三星 Galaxy win pro 3218 (hdpi)、 HTC one V (hdpi)、 中兴U985 (xhdpi)、Google Nexus 7 (xhdpi)。
③ 我在布局文件里声明了3个View, 第一个位于左上角,是一个线性布局,宽和高指定为120dp180dp(注意是dp哦), 第二个位于右上角,是一个ImageView,内容就是上面这张120px180px的, 第三个位于左下角也是一个线性布局,固定宽高,是120px180px。
我将这个放到一个Android工程里的drawable-hdpi目录
从上面的那种缩放关系表中我们可以知道,从hdpi目录中取, 运行在hdpi手机上宽高保持原始值,,运行在xhdpi手机上,宽高会乘以4/3, 也就是说会被拉扯变大, 但是的实际显示效果,即“视觉大小”怎么样呢。
下面是运行后的效果:
如图: 黑色区域是120dp180dp的View, 蓝色区域是120px180px的, 灰色区域是120px120px的View。
1, 可以看到使用dp的View(黑色区域)在不同分辨率,不同屏幕尺寸,不同屏幕密度的手机下,视觉大小看起来是一模一样的。
但是他们的实际像素值是不一样的: 120dp180dp -> (hdpi) -> 180px270px, 而120dp180dp ->(xhdpi)-> 240px360px。 由于屏幕密度的不同,缩放以后的像素可以显示出一样的视觉大小。
2, 蓝色的视觉大小也是一样的, 由于放到了hdpi目录下, 所以前两个手使用的是的原始像素120px180px, 而后两个手机对进行了放大, 参考上面的屏幕密度缩放关系表, 放大了4/3倍。 我通过对屏幕的截图,测量下来的结果的确是放大了这么多, 分别为160px240px。 由于屏幕密度的不同,它们显示出来的视觉大小是相同的。
3, 但是使用固定像素值的View就没那么幸运了, 它在hdpi的手机上看起来要比在xhdpi的手机上大一些。 要是在屏幕密度相差更大的手机上看的话, 这个区域的大小会相差很大。 这就是为什么Android推荐使用dp作为View的尺寸,而不是真实像素的原因了。
4, 经过反复试验,(实验结果就不贴图了,很多),得出一个结论,使用哪个目录下的(前提是只放在某一个目录中),在所有,不管是分辨率还是屏幕尺寸还是屏幕密度,3个参数都在改变的情况下,显示的视觉大小都和运行在这个目录对应屏幕密度手机上时的大小是一样的。
UI给工程师切多大图是合适的。
说说我之前走的冤枉路吧。
在之前, 设计师的交互和视觉设计都是基于480800的界面, 切图的时候会以480800为基础切一版, 然后在给所切的宽和高乘上个4/3,然后在出一版。
比如同一个120180的, 就会出两个版本, 一个是120180的一个是160240的。分别放到hdpi目录和xhdpi目录。
吃到的苦头是,UI很累, apk很大。T^T
这番探究下来, 发现直接基于7201280的视觉稿切一版就可以了。 将只放到xhdpi目录中,这样系统会在不同密度屏幕的手机中对进行合理的缩放, 而之前这个缩放工作竟然是人工完成的!
另: 如果想在xxhdpi的手机上显示的很好, 也可以基于1080P的屏幕设计, 这样的话就兼容所有低密度屏幕的手机, 而且也不会出现被拉扯的现象。
欢迎分享,转载请注明来源:品搜搜测评网