android的屏幕适配一直是开发者头疼的问题,因为android的设备大小不一,而且屏幕显示效果也不相同,如何对android进行屏幕适配是一个很大的挑战,为了应对不同的情况,需要仔细研究android对不同屏幕的定义。看过学渣的这篇博客,希望大家对屏幕适配有一个基本的了解。
1 android的屏幕大小
android的屏幕有大有小,为了对不同大小屏幕的设备提供最好的体验,需要对不同大小的设备进行不同的设计,首先遇到的问题就是android对屏幕大小的区分。
android的屏幕问题在官网有详细说明,,作为一名学渣,需要细细研读,首先android把屏幕分为四种大小:small,normal,large,xlarge,这四种屏幕首先是直观的区分,即对设备的对角线用尺子量一下,用英寸做单位进行区分,比如学渣用的红米就是4.7英寸,属于normal,具体分类如图1所示:
图1 android屏幕大小区分
如果你的程序获知android设备屏幕后,根据大小不同可以采用不同的布局方案,但是我们写程序时,进行布局时,不可能用英寸进行布局,先假设我们使用像素(px)进行布局,但是这里会遇到一个问题,这里需要介绍新的term,请看2。。。。。
2 屏幕的分辨率和密度
这里遇到的问题需要看几个术语,android官网上去后有几个术语介绍,学渣先为大家介绍分辨率和密度
分辨率(Resolution):The total number of physical pixels on a screen. 即一个设备的物理像素,如1280*720,大家可以自己计算。
密度(Screen density):The quantity of pixels within a physical area of the screen; usually referred to as dpi (dots per inch).一般我们的密度的单位是像素数目/平方英寸,但是这里推荐了一个新的密度表示方法,就是每英寸的像素数目(dpi)。我们以后用到的密度就是这个dpi。
android里用分辨率和密度这两个域来记录设备的真实尺寸,采用密度的主要原因(学渣猜的)应该是“去英寸化”,即在程序中不要出现英寸这个单位,因此用密度和分辨率这两个值可以保存设备的真实尺寸。
对于一个程序而言,它可以获取到屏幕的分辨率和尺寸,进而密度=分辨率/尺寸,可以算出尺寸,在android里,获取密度尺寸可以参考这里。我们这里用一个小程序来求两个设备的分辨率和密度。学渣定义了两台avd,尺寸都是4.7英寸,设备1的分辨率为800*1280,设备2的分辨率为480*800,测试代码如下:
package com.example.testscreen; import android.os.Bundle; import android.app.Activity; import android.util.DisplayMetrics; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); //得到设备的分辨率,即宽和高的像素数目 int height = metrics.heightPixels; int width = metrics.widthPixels; System.out.println("the height is "+height +" the width is" + width); //得到设备的密度 int density = metrics.densityDpi; System.out.println("the density is " + density); } }
设备1的输出是:
06-09 00:10:17.188: I/System.out(2041): the height is 1184 the width is768 06-09 00:10:17.188: I/System.out(2041): the density is 320设备2的输出是:
06-09 00:45:35.085: I/System.out(2088): the height is 736 the width is480 06-09 00:45:35.085: I/System.out(2088): the density is 213
从两个设备的输出可以知道,其实学渣是定义了两个4.7英寸的avd,但是有着不同的分辨率,(android里有底部栏,看起来有点不一样),这两个例子说明了一个问题:相同大小的手机,可以有不同的分辨率,进而就有不同的密度喽,(因为密度=分辨率/大小)。
3 程序判断屏幕大小
每个程序都需要判定屏幕的大小,进而选择合适的布局(后面会说),如何判定大小(设备的真实尺寸,可以理解为设备对角线的英寸数)呢,就根据2所提到的两个参数来判断,一个是分辨率,一个是密度,用设备1而言,知道height是1184像素(px),其密度为320dpi(像素/英寸),则高度的具体值就是1280/320=4(英寸),宽度为800/320=2.5 ,用勾股定理算出对角线的长度,(学渣这里没有细算)再和图1匹配,得到这个设备的屏幕大小尺寸。
屏幕大小判定之后,首先需要在mainfest声明支持的屏幕大小,如:
<supports-screens android:largeScreens="true" />
要想要好的用户体验,程序可以根据不同的大小选择不同的布局,android官方文档里也提到了,可以对不同的大小,设置不同的layout,如res/layout-large就是large屏幕时所采用的布局。
官方文档里有这么几句话要注意:Beginning
with Android 3.2 (API level 13), the above size groups are deprecated and you should instead use the sw<N>dp
configuration
qualifier to define the smallest available width required by your layout resources. For example, if your multi-pane tablet layout requires at least 600dp of screen width, you should place it inlayout-sw600dp/
.即对于3.2以上的,直接采用dp(dp相当于一种程序中的英寸大小)进行判断屏幕的宽度,进而选择不同的布局,如/res/layout-sw600dp,就是宽度要求是600dp以上的我们就选择这个布局。不过意思和small,large等一样,只不过把大小换成了具体的数字。
3 去英寸化
上面我们提到了去英寸化,如何让一个程序能够很好的显示大小呢,似乎可以采用像素?但是这是完全不可以的。先举一个简单的例子说明像素的缺陷,还是采用上述的设备1和设备2进行测试,我们在设备1和设备2都定义一个button,宽度和高度都为200px(像素),效果如图2所示:
图2 相同大小的手机,相同的像素大小的button
其实这个结果一点也不意外,这是因为两个button的像素大小虽然一样,但是密度不同,而最后的真实大小是按照英寸来画的,因为密度=像素/英寸,则 真实大小(英寸数)=像素/密度。那么这个问题怎么破,因为我们的程序一定是在相同大小的屏幕上有相同的大小,如果两个空间的大小一样,则是其英寸数相等,而英寸数又不能直接写在程序里,于是乎出现一个逆天的术语,dp。其实在2里我们看到过这个dp,那么什么是dp呢?
dp在官网里叫Density-independent pixel (dp),即密度无关的像素,即可以摆脱密度的缠绕,就是前面我所提到的一种具有“去英寸化”功能的新的单位,我们先不提dp的具体计算(后面会说),我们就先假设这个dp就是一个全新的度量单位,让相等的dp在不同密度的屏幕里有相等的长度,比如1dp无论你是在设备1还是设备2,大小都是相等。这就是解决了“去英寸化”的问题。
4 dp的应用与图片问题
通过3的描述,我们应该可以知道,在layout里任何的控件都采用dp就可以保证显示一致的问题了。这也是google所推荐的。
但是对于图片这种外来户,我们可以规定它在layout中的大小,假如我们规定了图片的宽度1英寸(可以转为dp,后面会将),对于一张图片,其真实的宽度为15像素,在密度为3dpi的屏幕中,可以显示3个像素,这时需要丢掉12个像素,图片一定极为不清晰;在密度为15dpi的屏幕里可以显示15个像素,显示完全。这就有了分辨率的问题,在宽度都为1英寸的情况下,肯定是能够显示全部15个像素的图片清晰,怎么能让不同密度的屏幕显示的照片都比较清晰呢,我们可以对不同密度的屏幕选择不同的图片,即高密度选择高清图片。对于任何一张图片,我们都可以做三张,一张低分辨率,一张高分辨率,一张中间值,对于高密度的屏幕,比如密度为15,我们选择一张分辨率较高的图片(就是大的图片),如15英寸的,对于密度为3的,我们让它显示一张分辨率为3的,则保证了不会丢失信息,从而保证图片清晰。
对于不同密度的屏幕,可以通过/res/drawable-hdpi等进行选择图片。这个官网也有。
5 dp的计算
其实我们没必要对dp进行计算,但是为了便于理解,我还是把dp的计算说一下, px
= dp * (dpi / 160)
另外:android里字体的大小采用sp,具体的还没有研究,不过作用估计和dp差不多。
这篇博客花了学渣一个中午的时间,对于android的学习,学渣认为应该以官网为主要参考,如果本文内容有误,欢迎指出,谢谢!
原文地址:http://blog.csdn.net/zhao123h/article/details/29564071