开发中屏幕适配那些事

强烈感谢这个屏幕适配的文章

Android 屏幕基本单位;

dip: Density independent pixels ,设备无关像素
dp: 就是dip
px: 像素
dpi: dots per inch .一英寸多少个像素点
density: 密度
屏幕分辨率: 横纵2个方向的像素点的数量,常见取值: 480800 ; 320480 1px=1个像素点
屏幕尺寸: 对角线长度 1英寸 = 2.54厘米
屏幕比例: 知道对角线长 可通过屏幕比例确定屏幕边长 例如 4:3 16:9;

屏幕尺寸

对角线长度

1英寸 [单位:inch]= 2.54厘米

屏幕分辨率:

横纵2个方向的像素点的数量.

常见取值: 480 * 800 ; 320 * 480 1px=1个像素点

dpi

Dot per inch 屏幕像素密度 一英寸内有多少像素

计算方法:


dpi= \sqrt{(屏幕横向像素^2+屏幕纵向像素^2)}/屏幕尺寸

屏幕分辨率为:2340*1080 尺寸为6.39
dpi =

\sqrt{{2340^2+1080^2}}/6.39 = 403 [px/inch]
PPI只能用来描述屏幕的显示密度,也不能描述图片的清晰度 DPI才能用来描述图片显示的清晰度,表示图片在屏幕上的显示效果。
当图片分辨率与屏幕显示像素相同时, DPI与PPI值相等

当图片分辨率大于屏幕显示像素时, DPI与PPI值相等,图片显示较差

当图片分辨率小于屏幕显示像素时, DPI值

dp/dip

dip和dp是一个意思 密度无关像素

规定以160dpi为基准,1dip=1px,如果密度是320dpi,则1dip=2px,以此类推。


density

密度,表示一个dp多少像素. 一般计算方式

density = dpi/160

dp = density*px

密度类型 代表的分辨率(px) 像素密度范围 屏幕密度(dpi) 换算(px/dp) 比例
低密度(ldpi) 240x320 120dpi以下 120 1dp=0.75px 3
中密度(mdpi) 320x480 120dpi ~ 160dpi 160 1dp=1px 4
高密度(hdpi) 480x800 240dpi ~ 320dpi 240 1dp=1.5px 6
超高密度(xhdpi) 720x1280 240dpi ~ 320dpi 320 1dp=2px 8
超超高密度(xxhdpi) 1080x1920 320dpi ~ 480dpi 480 1dp=3px 12

这里0.75 1 1.5等等为density; density = dpi/160 ;

SW适配

SW全称是Smallest Width,表示最小宽度,例如一个适配文件夹values-sw411dp表示如果手机的最小宽度是411dp,那么就命中该文件夹,使用的配置都是这个文件夹下的。

代码中可以用getResources().getConfiguration().smallestScreenWidthDp获取sw

sw的理论上计算原理

例如:已知一个5.1寸手机的分辨率为1440*2560(2k屏),求sw?
解析:sw = 1440/desity,desity = dpi/160,dpi = 对角线像素/屏幕尺寸,对角线像素用勾股定理求,多么简单的一道题。

对角线长度 = \sqrt{(1440^2 + 2560^2)} = 2937px

dpi = \frac{对角线长度}{屏幕尺寸} = \frac{2937px}{5.1 inch}=575 px/inch 

density = \frac{dpi}{160} = \frac{576}{160} = 3.5

sw = \frac{宽度像素}{density} = \frac{1440}{3.5} = 411dp

但实际上我们通过代码获取的参数结果并不是这个.

原理解析

查看系统源码:

density =  DENSITY_DEVICE / (float)DENSITY_DEFAULT;

也就是

density =  getDeviceDensity() / (float)160;

getDeviceDensity()源码:

private static int getDeviceDensity() {
    return SystemProperties.getInt("qemu.sf.lcd_density",SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT));
}

这个方法是获取设备密度,这个密度是通过系统的配置项qemu.sf.lcd_density或者ro.sf.lcd_density指定的。为了验证我们的猜想,我们用adb shell看看能不能找到这个配置项。

shell@trltechn:/ $ cd system
shell@trltechn:/system $ cat build.prop|grep density                        
ro.sf.lcd_density=640

所以dpi以系统设置的为准.因此

density = \frac{系统的dpi}{160}

然后 sw = \frac{宽度像素}{density} 


项目之中使用的屏幕适配方案

一个px/dp适配以及jar包下载链接

获取设备最小宽度代码为

     int smallestScreenWidthDp = getResources().getConfiguration().smallestScreenWidthDp;

 DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int heightPixels = ScreenUtils.getScreenHeight(this);
        int widthPixels = ScreenUtils.getScreenWidth(this);
        float density = dm.density;
        float heightDP = heightPixels / density;
        float widthDP = widthPixels / density;
        float smallestWidthDP;
        if(widthDP < heightDP) {
            smallestWidthDP = widthDP;
        }else {
            smallestWidthDP = heightDP;
        }
        
        public class ScreenUtils {

    /**
     * 获取屏幕宽度
     *
     * @param context Context
     * @return 屏幕宽度(px)
     */
    public static int getScreenWidth(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Point point = new Point();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            wm.getDefaultDisplay().getRealSize(point);
        } else {
            wm.getDefaultDisplay().getSize(point);
        }
        return point.x;
    }

    /**
     * 获取屏幕高度
     *
     * @param context Context
     * @return 屏幕高度(px)
     */
    public static int getScreenHeight(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Point point = new Point();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            wm.getDefaultDisplay().getRealSize(point);
        } else {
            wm.getDefaultDisplay().getSize(point);
        }
        return point.y;
    }
}

使用步骤

1.根据UI设计图的尺寸为标准,安卓一般为360dp.一般UI都是以ios的标准出图那也就是375dp,通过插件自动生成对应的dimens文件;

插件链接
链接:https://pan.baidu.com/s/1kdhhnn2Q8ysy86qQpuQ1Gw 
提取码:43dh 

dimens链接
链接:https://pan.baidu.com/s/1Eb65zeEtnr1RaTCIR295ow 
提取码:irna 

一般为向下取值,sw值一般为手机宽度px/density得到 density通过dpi/160得到. 但是有的设备dpi值系统设置的不同 . 则需要通过adb shell得到

通过此方式插入框架.png
2.项目的默认values需要一份默认值.即dimens

图片.png

有需要新增的在这里增加即可

3.任意文件目录点击
图片.png

选择要放入的module中,即可;

4.在res里可看到这些文件
图片.png
5.配置含义
图片.png

双击打开

图片.png

你可能感兴趣的:(开发中屏幕适配那些事)