表示屏幕的物理像素,例如 1080×1920
简称dpi,我们常说的像素密度,表示1英寸上对应有多少个像素,例如 160dpi、320dpi、440dpi、480dpi.
以1080×1920的5英寸手机为例:
宽:1080像素
高:1920像素
对角线(5英寸):根据勾股定理算出大约2203像素
每英寸上大约有:440像素 = 2203/5
所以这个手机的像素密度是440dpi
dip的别称,dp是Android上为了适配不同屏幕设备而定义的一种抽象单位,1dp可以理解为屏幕上的一个点,这个点在不同屏幕分辨率上占用的像素不一样,比如在屏幕分辨率高的设备上占用更多像素,在分辨率小的设备上占用更少的像素,从而让它整体上来看显示的比例相对屏幕大小是一样的
与densityDpi类似,densityDpi表示1英寸上对应有多少个像素(对应屏幕物理像素密度); 而density则表示1dp上有多少个像素,可以理解为dp密度(对应抽象的屏幕密度);它可以用于dp和px之间转换
计算公式:density = px/dp;
它与densityDpi之间的关系是固定的:density = densityDpi / 160
例如:
当densityDpi=160时,density=1,也就是1英寸上有160个像素,1dp就代表1像素
当densityDpi=320时,density=2,也就是1英寸上有320个像素,1dp就代表2像素
…
为什么dip用160作为标准呢?主要有两个原因
//kotlin
var displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getRealMetrics(displayMetrics) //从WindowManager获取DisplayMetrics
displayMetrics = resources.displayMetrics //从Resources获取DisplayMetrics
displayMetrics.widthPixels //屏幕宽度
displayMetrics.heightPixels //屏幕高度
displayMetrics.density //dp和px比例
displayMetrics.densityDpi //像素密度
val point = Point()
windowManager.defaultDisplay.getRealSize(point);
point.x //屏幕宽度
point.y //屏幕高度
fun dp2px(context: Context, dpValue: Float): Int {
val density = context.resources.displayMetrics.density
return (dpValue * density + 0.5).toInt()
}
fun px2dp(context: Context, pxValue: Float): Int {
val density = context.resources.displayMetrics.density
return (pxValue / density + 0.5).toInt()
}
fun setCustomDensity(activity :Activity){
val designWidthDp = 360 //假设设计图按照宽度360dp大小进行设计
var displayMetrics = activity.resources.displayMetrics
//计算出每个dp上有多少个像素,也就是density值
val targetDensity = displayMetrics.widthPixels / designWidthDp
// 重新计算dpi值
val targetDensityDpi = targetDensity * 160
displayMetrics.density = targetDensity.toFloat()
displayMetrics.densityDpi = targetDensityDpi
//Application的DisplayMetrics也要设置
displayMetrics = activity.application.resources.displayMetrics
displayMetrics.density = targetDensity.toFloat()
displayMetrics.densityDpi = targetDensityDpi
}
dp在Android只是个抽象单位,最终还是会根据density转换成px值;
假如按照屏幕宽度540dp设计UI图,绘制一条长度为540dp的线条,代码中设置该线条长度为540dp
在设备1上:
分辨率1080×1920
转换dp: 540dp x 960dp
像素密度:320dpi
density = 2
线条实际长度:540dp * 2(density) = 1080px
显示效果:长度刚好是屏幕的宽度,与设计图效果一致
在设备2上:
分辨率:1080×1920
转换dp: 1080dp x 1920dp
像素密度:160dpi
density = 1
线条实际长度:540dp * 1(density) = 540px
显示效果:长度只有屏幕宽度的一半,与设计图差别很大
经过适配重新调整设备2的DisplayMetrics参数后:
newDensity=1080(屏幕分辨率)/540(设计图屏幕宽度)=2
线条实际长度:540dp * 2(newDensity) = 1080px
显示效果:长度刚好是屏幕的宽度,与设计图效果一致