适配不同分辨率
在drawable中的图片在不同密度的设备上显示时,在屏幕上的占比是不一样的。
如:160px的图片,在800x480的屏幕上显示:
密度是:
160dpi时,占屏幕的三分之一 (=160px/480px)。
240dpi时,占屏幕的二分之一(>160px/480px)。
如何保持图片在不同密度的设备上,图片显示相同的像素数?
方法A:
为不同密度的设备,准备相应的图片,放在对应的drawable-?dpi中。
优点:可以为不同密度的设备,准备对应密度的图片,可以做到图片在哪种密度上都很清晰细腻。
缺点:图片比较多,增加图片制作的工作量;
方法B:
只准备一组图片,将图片放到drawable-nodpi中。
优点:减少了图片的数量;
确定:图片可能被拉伸而导致不细腻;
方法C:
使用px指定图片的大小
理解DPI。DPI是密度density的测量单位,dots per inch 每英寸内的像素数。
理解DIP。DIP是指定大小的单位,device independent pixels设备独立像素。
应该是Density-independent pixel 即与设备的密度无关,有DIP指定的控件大小,在不同密度的设备上,显示的大小相仿。
pixels = dip * (density / 160)
注:显示图片的大小与图片本身的dpi 没有关系。
分辨率问题在手机应用上是一个非常重要的问题,举个简单例子,默认情况下,一个24×6的图片,在你做图的时候,是4个6×6的分割图片组合成的一个整体图片,那么在不同density下,如果你切割图片,这个整体图片则会出现不同的大小。
1、在160的density(240×320就是160的)模式下,该图片没有任何缩放,就是24×6;你用宽6、高6可以正确切片;
2、在240的density(480×800)模式下,该图片就会被放大1.5倍(240/160),因此,这个图片实际就是32×9,如果你还用宽6、高6去切片,就会出现问题,这个时候,正确的做法是
要么使用Bitmap的option设置,在从Resource读取资源的时候,表明不缩放,但默认情况下,Android系统使用dip来读取你分辨率无关的单位,所以,你必须显示的设置option,告诉android系统不要使用dip来自适应。
1: private Bitmap decodeResource(Resources resources, int id) {
2: TypedValue value = new TypedValue();
3: resources.openRawResource(id, value);
4: BitmapFactory.Options opts = new BitmapFactory.Options();
5: opts.inTargetDensity = value.density;
6: return BitmapFactory.decodeResource(resources, id, opts);
7: }
但是,这种方法不推荐使用,这样破环了DIP的初衷,最好以下面两种方式来处理。
将切片的宽乘1.5,高乘1.5,也就是说,以9×9的宽高去切片。
直接以4分之一去切割。
下面说说官方文档对分辨率问题的解释:
http://developer.android.com/guide/practices/screens_support.html
一、多分辨率支持
在设计之初,Android系统就被设计为一个可以在多种不同分辨率的设备上运行的操作系统。对于应用程序来说,系统平台向它们提供的是一个稳定的,跨平台的运行环境,而关于如何将程序以正确的方式显示到它所运行的平台上所需要的大部分技术细节,都由系统本身进行了处理,无需程序的干预。当然,系统本身也为程序提供了一系列API,所以在目标平台的分辨率是可以完全确定的情况下,程序也可以精确的控制自身在目标平台上的界面显示方式。
二、术语和概念
屏幕尺寸
屏幕的物理尺寸,以屏幕的对角线长度作为依据(比如2.8寸,3.5寸)。
简而言之,Android把所有的屏幕尺寸简化为三大类:大,正常,和小。
程序可以针对这三种尺寸的屏幕提供三种不同的布局方案,然后系统会负责把你的布局方案以合适的方式渲染到对应的屏幕上,这个过程是不需要程序员用代码来干预的。
屏幕长宽比
屏幕的物理长度与物理宽度的比例。程序可以为制定长宽比的屏幕提供制定的素材,只需要用系统提供的资源分类符long和notlong。
分辨率
屏幕上拥有的像素的总数。注意,虽然大部分情况下分辨率都被表示为“宽度×长度”,但分辨率并不意味着屏幕长宽比。在Android系统中,程序一般并不直接处理分辨率。
密度
以屏幕分辨率为基础,沿屏幕长宽方向排列的像素。
密度较低的屏幕,在长和宽方向都只有比较少的像素,而高密度的屏幕通常则会有很多 ——甚至会非常非常多——像素排列在同一区域。屏幕的密度是非常重要的,举个例子,长宽以像素为单位定义的界面元素(比如一个按钮),在低密度的屏幕上会显得很大,但在高密度的屏幕上则会显得很小。
密度无关的像素(DIP)
指一个抽象意义上的像素,程序用它来定义界面元素。它作为一个与实际密度无关的单位,帮助程序员构建一个布局方案(界面元素的宽度,高度,位置)。
一个与密度无关的像素,在逻辑尺寸上,与一个位于像素密度为160DPI的屏幕上的像素是一致的,这也是Android平台所假定的默认显示设备。在运行的时候,平台会以目标屏幕的密度作为基准,“透明地”处理所有需要的DIP缩放操作。要把密度无关像素转换为屏幕像素,可以用这样一个简单的公式:pixels = dips * (density / 160)。举个例子,在DPI为240的屏幕上,1个DIP等于1.5个物理像素。我们强烈推荐你用DIP来定义你程序的界面布局,因为这样可以保证你的 UI在各种分辨率的屏幕上都可以正常显示。
·三种主要的尺寸:大,正常,小;
·三种不同的密度:高(hdpi),中(mdpi)和低(ldpi)。
低密度(120),ldpi
中密度(160),mdpi
高密度(240),hdpi
小屏幕
·QVGA(240×320),2.6~3.0寸
普通屏幕
·WQVGA(240×400),3.2~3.5寸
·FWQVGA(240×432),3.5~3.8寸
·HVGA(320×480),3.0~3.5寸
·WVGA(480×800),3.3~4.0寸
·FWVGA(480×854),3.5~4.0寸
大屏幕
·WVGA(480×800),4.8~5.5寸
·FWVGA(480×854),5.0~5.8寸
Adnroid1.6或以上SDK,在AndroidManifest.xml中提供新的一个元素<supports-screens>用于支持多屏幕机制。
<supports-screens
android:largeScreens="true" 是否支持大屏
android:normalScreens="true" 是否支持中屏
android:smallScreens="true" 是否支持小屏
android:anyDensity="true" 是否支持多种不同密度
/>
三、Android提供3种方式处理屏幕自适应
一).预缩放的资源(基于尺寸和密度去寻找图片)
1.如果找到相应的尺寸和密度,则利用这些图片进行无缩放小时。
2.如果没法找到相应的尺寸,而找到密度,则认为该图片尺寸为 "medium",利用缩放这个图片显示。
3.如果都无法匹配,则使用默认图片进行缩放显示。默认图片默认标配 "medium" (160)。
二).自动缩放的像素尺寸和坐标(密度兼容)
1.如果应用程序不支持不同密度android:anyDensity="false",系统自动缩放图片尺寸和这个图片的坐标。
(代码中体现)
2.对于预缩放的资源,当android:anyDensity="false",也不生效。
3.android:anyDensity="false",只对密度兼容起作用,尺寸兼容没效果
三).兼容模式显示在大屏幕,尺寸(尺寸兼容)
1.对于你在<supports-screens>声明不支持的大屏幕,而这个屏幕尺寸是normal的话,系统使用尺寸为 ("normal")和密度为("medium)显示。
2. 对于你在<supports-screens>声明不支持的大屏幕,而这个屏幕尺寸是larger的话,系统同样使用尺寸为 ("normal")和密度为("medium)显示,不过会出现一层黑色的背景。不是居中显示。
系统默认应用支持DIP单位的,三个使用DIP的地方:
1.加载资源时,使用DIP实现预缩放的资源。
2.在Layout使用DIP,系统自动完成缩放。
3.在应用程序中,自动缩放一些绝对像素。
(只有在android:anyDensity="false"生效)即屏幕自适应方式二
4.像素单位都使用DIP,文本单位使用SP