由于市场上采用安卓系统的设备种类很多,安卓开发人员不得不进行麻烦的匹配工作。
匹配任务包括匹配安装了不同Android版本的设备,以及匹配不同屏幕上的设备。
屏幕拟合包括以下内容:
屏幕大小(small、normal、large、xlarge,这些在Android 3.2和更高版本中不再推荐,而是使用sw600dp、最小宽度、最小高度等最小屏幕宽度) ) ) ) ) ) ) )。
屏幕方向(端口纵向画面、焊盘横向画面) )。
屏幕像素密度(ldpi、mdpi、hdpi、xhdpi、xxhdpi () ) ) ) ) ) ) ) ) ) ) )。
本文主要介绍屏幕像素密度自适应的相关知识。
考虑以下问题。
假设一个设备的屏幕像素密度为320dpi,并且48x48大小的图像位于android工程的res/drawable-hdpi目录中,然后在布局文件中使用ImageView浏览该图像。 其中,ImageView的宽度高度设置为遵循内容,即wrap_content。 屏幕上显示的ImageView是
答案: 64px * 64px
如果读者不知道如何计算,请参考以下内容。
首先介绍一些概念。
画面像素密度是指单位长度的画面显示像素,即常见的dpi(dotsperinch ),是指每英寸的点数。 密度越高,画面越清晰。
Android按区间将像素密度分为几个:
ldpi -低dpi,低密度
mdpi - medium dpi中的密度
高密度高密度dpi
xh dpi-extra高dpi超高密度
xxhdpi- extra extrahigh dpi超高密度
xxhdpi---- extraextraextrahighdpi超超高密度
无论设备的像素密度如何,都可以找到相应的分类。
创建新的Android项目后,drawable-xxx目录将显示在res目录下。 这是对应于不同像素密度的资源。
这些目录怎么用呢? 如何进行像素密度匹配?
首先,Android以mdpi即中密度为基准线,即密度160 dpi为基准值。
公式中,建议用与画面像素密度无关的单位dp记述button等控件的宽度、高度。 dp与px (以像素为单位)的关系为px = dp * (dpi /160)。 也就是说,如果设备的像素密度为320dpi,则在1dp=2px、宽度为160dpi的button中,160dpi的320dpi设备占160*2=320px。 这样,不同设备的相对大小看起来相同,button不会“变小”。
然后,根据像素密度,系统给出相应的比例和倍数,如下所示:
分类目录ldpimdpihdpixhdpixxhdpixxxxhdpi密度(dpi(160~240~320~480~640影像比例1.523468倍数0.75x1x1.5x2x3x4x
根据上表,如果知道像素密度,就知道对应的资源目录,系统会优先在该目录中查找图像,如果找不到,就从其他目录中查找图像。
因此,为了应对密度不同的设备,获得更好的结果,需要准备不同画质的图像。
在新Android项目中,默认自动机图标的大小取决于密度目录,其比例与表的比例匹配,准备资源图像时也按该比例进行。
后面一行的“倍数”与比例相对应,其作用将在后面说明。
回到开头的问题,怎么找到答案? 作者做了测试。
测试型号:
三星n719 (像素密度: 320 dpi屏幕宽度高度:720x1280 () ) ) ) ) ) ) ) )。
三星i619 (像素密度: 160 dpi屏幕宽度高度:320x480 ) ) ) ) ) ) ) ) )。
测试图像:取48x48大小的图像(新Android项目的mdpi目录下的默认自动机图标),分别为drawable、drawable-mdpi、drawable-hdpi延迟
xml布局控件: 3个ImageView,Android : layout _ width=' wrap _ content ',Android 3360 layout _ height=' wrap _ codth
布局文件:
? XML版本=' 1.0 '编码=' utf-8 '? relativelayoutxmlns 3360 Android=' http://schemas.Android.com/apk/RES/Android ' Android 3360 layout _ width=' match
oid:layout_height="match_parent" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="fragment two" android:background="@color/green" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:background="@color/gray" android:src="@drawable/default_test" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:background="@color/gray" android:src="@drawable/mdpi_test" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:background="@color/gray" android:src="@drawable/hdpi_test" /> </LinearLayout> </RelativeLayout>
测试结果:(测量三个ImageView宽度和高度,单位为px)
N719:
引用drawable,drawable-mdpi目录下图片的ImageView大小都为 96x96
引用drawable-hdpi目录下图片的ImageView大小为 64x64
I619:
引用drawable,drawable-mdpi目录下图片的ImageView大小都为 48x48
引用drawable-hdpi目录下图片的ImageView大小为 32x32
N719 测试截图:
可以看到最后一个ImageView 跟其他两个比变小了。
由于我们设置ImageView宽高为wrap_content,那么其大小将跟图片大小一样,需要知道如何计算图片的宽高。
经过多次测试,可推出以下结论:
Android系统加载图片时设置图片宽高可能的处理流程为:(假设ImageView采用默认的scale type)
1.获取图片文件宽度width
2.width的单位为dp,转换成px单位宽度 newWidth = width * (dpi/160)
3.根据上述表格中mdpi,hdpi等的倍数,newWidth除以这个倍数得到最终图片宽度
其中除以倍数的过程也可能发生在步骤1,不过结果是一样的。
高度的计算方法类似。
对应上面的测试例子:
1.获取图片文件宽度48
2.转换成px单位宽度 newWidth = 48 * (320 / 160) = 96
3. 由于图片存放在hdpi目录,除以hdpi对应倍数1.5 ,得到图片宽度为 96/1.5 = 64
将I619设备测试结果验证,符合以上结论。后面尝试在ldpi中添加同样大小图片,测试ImageView宽度为 96/0.75 = 128,ImageView变大了,计算结果也与以上结论一致。
如何消除这种变大变小的现象呢?
将不同目录的图片大小换一下,比如hdpi下图片大小换成72x72,根据结论得出最后计算的图片宽度为 72 * (320/160) / 1.5 = 96 px ,这样ImageView看起来就不会变小了。
这里72x72就是系统默认hdpi下机器人图标大小,按照上述表格给的比例放置图片就不会有ImageView控件大小不一样的问题。
另外本测试可以看出,放在drawable目录的情况跟mdpi目录的情况一致,推测这两个对应的比例和倍数应该是一样的。
将ImageView的宽度高度设成固定大小比如48x48 dp,在N719上测试情况如下:
布局文件:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:orientation="vertical" > <TextView android:layout_width="48dp" android:layout_height="48dp" android:text="fragment one" android:background="@color/red" /> <ImageView android:layout_width="48dp" android:layout_height="48dp" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:background="@color/gray" android:src="@drawable/ldpi_test" /> <ImageView android:layout_width="48dp" android:layout_height="48dp" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:background="@color/gray" android:src="@drawable/default_test" /> <ImageView android:layout_width="48dp" android:layout_height="48dp" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:background="@color/gray" android:src="@drawable/mdpi_test" /> <ImageView android:layout_width="48dp" android:layout_height="48dp" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:background="@color/gray" android:src="@drawable/hdpi_test" /> <ImageView android:layout_width="48dp" android:layout_height="48dp" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:background="@color/gray" android:src="@drawable/hdpi_test_2" /> </LinearLayout> </RelativeLayout>
可以看出,ImageView固定大小后,如果不设置scale type,图片会按ImageView大小来显示,如果设置同样大小图片,ldpi 会压缩大小(128 -> 96),hdpi会拉伸大小(64 -> 96)
最后一个ImageView引用的图片@drawable/hdpi_test_2 其大小是72x72,可以看出它的画质最为清晰,这也正体现根据屏幕像素密度适配的重要性。