强烈感谢这个屏幕适配的文章
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得到
2.项目的默认values需要一份默认值.即dimens
有需要新增的在这里增加即可
3.任意文件目录点击
选择要放入的module中,即可;
4.在res里可看到这些文件
5.配置含义
双击打开