1. dpi是dot per inch,每英寸多少点,ppi是 Pixel per inch,每英寸像素数,针对显示器的设计时,dpi=ppi。

而安卓代码中常用density(点密度)来表示。ppi的计算方式呢可以根据勾股定理以及小学数学知识就能算出了哈哈,

例如小米2s分辨率1280*720,4.3寸。

android ppi屏幕适配 ppi适配器_android开发

这样的话可以得到ppi=(√1280^2+720^2)/4.3=341.53...可以粗略估计为320ppi

2.dip或dp(device independent pixels)设备独立像素。是安卓开发中独有的单位,规定在160ppi的设备上将1px设为1dp。什么意思呢?

先看下面几张图

android ppi屏幕适配 ppi适配器_android ppi屏幕适配_02


这是分别在三种不同设备上显示一张尺寸一样的图片效果,我们发现规律即ppi越低图片显示越大,因此要让不同设备显示相同大小的图片需要缩放图片。

这也就有了在开发工作中res资源分为几个目录分别是mdpi,hdpi,xhdpi,xxhdpi等。解决上述问题我们需要如下图所示

android ppi屏幕适配 ppi适配器_dp_03

根据缩放比例我可以得到一个等比例公式即,px1/px2=ppi1/ppi2。

选定一个ppi值作为基础绘制图片,用ppi的比值计算出图片缩放比例就可以适配各种屏幕

px2=px1*(ppi2/ppi1)

安卓选定的这个基础值就是160ppi

px2=px1*(ppi2/160)

我们已经解决了图片放大缩小的问题,还需要一个单位用来描述长度(因为px不固定,inch不方便)。

安卓就创造了一个新的单位dp,中文名:设备独立像素。并且规定在160ppi的屏幕上,1dp=1px。

因此上述的公式就变成了

px=dp*(ppi/160)


3.sp安卓自定义单位来描述字体的大小,原理同dp一样。

对于sp与点密度之间的对应关系如下:

android ppi屏幕适配 ppi适配器_android开发_04


4.好了说了那么多概念应该用代码验证一下了。对于上述讲到的各个参数都可以通过DisplayMetrics类得到

public class ThirdActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_second);

        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);

        String strScreenDIP = "";
        strScreenDIP += "The logical density of the display: " + dm.density + "\n";
        strScreenDIP += "The screen density expressed as dots-per-inch: " + dm.densityDpi +"\n";
        strScreenDIP += "The absolute height of the display in pixels: " + dm.heightPixels +"\n";
        strScreenDIP += "The absolute width of the display in pixels: " + dm.widthPixels + "\n";
        strScreenDIP += "A scaling factor for fonts displayed on the display: " + dm.scaledDensity + "\n";
        strScreenDIP += "The exact physical pixels per inch of the screen in the X dimension: " + dm.xdpi + "\n";
        strScreenDIP += "The exact physical pixels per inch of the screen in the Y dimension: " + dm.ydpi + "\n";

        TextView textScreenDIP = (TextView)findViewById(R.id.text_view);
        textScreenDIP.setText(strScreenDIP);
    }
}



运行在三个设备(小米2s,nexus 7, 三星tab)上分别如下图所示:

android ppi屏幕适配 ppi适配器_ppi_05

android ppi屏幕适配 ppi适配器_android ppi屏幕适配_06

android ppi屏幕适配 ppi适配器_android ppi屏幕适配_07

可以看到三星屏幕分辨率很低。

设备/参数

dm.density

dm.densityDpi(ppi)

dm.heightPixels dm.widthPixels

dm.scaledDensity

dm.xdpi

dm.ydpi

小米2s

2.0

320

1280*720

2.0

160.421

160157

N7

2.0

320

1824*1200

2.0

320.842

322.966

三星

1.0

160

800*1280

1.0

149.824

149.411

首先第一个参数dm.density代表逻辑的点密度(The logical density of the display)默认1.0的情况下DPI为160,同样参数dm.scaledDensity代表字体缩放因子(A scaling factor for fonts displayed on the display)故这两个参数和PPI以及android开发中的资源包命名存在如下对应:

dm.density

dm.scaledDensity

PPI

资源命名

1.0x

1.0x

160

mdpi

1.5x

1.5x

240

hdpi

2.0x

2.0x

320

xhdpi

3.0x

3.0x

480

xxhdpi

4.0x

4.0x

640

xxxhdpi

因此根据上述对应我们在res/drawable-mdpi/下跟换了图片换成了如三星平板显示一样的图片,而在小米2s和nexus 7上没有更换因此与三星显示的效果就不一样了。

对于最后一组参数dm.xdpi和dm.ydpi是指准确的dpi(The exact physical pixels per inch of the screen in the X dimension.)对于小米2s的这组数据为什么不约等于dm.densityDpi我很困惑????在其他设备上(跟小米配置相似的如大神F1和魅族MX)最后一组参数都约等于densityDpi。随后我又换了一台小米2s,而这台2s最后一组数据约等于320,那么为什么我的小米手机2s最后一组数据确是160多呢(我的2s刷成了基于android4.4.4的miuiv6了)

再有一点就是根据屏幕的大小自定义适配,如下表展示:

android3.2以前:                                                             android3.2以后:

android ppi屏幕适配 ppi适配器_android开发_08

                

android ppi屏幕适配 ppi适配器_android ppi屏幕适配_09


我们在适配图标的时候,例如在Nexus 7上就可以将专门为N7设计的图标放到drawable-sw600dp目录下。

因为N7的dp约等于600(比600大点)。