本文涉及到 px、sp、dp(dip)、分辨率和dpi(像素密度)的概念,以及像素密度的计算 和 px 转换 dp 的计算公式、px、sp、dp互转的java工具类封装。
分辨率:指手机屏幕像素个数,如 720 * 1280 指屏幕宽有720个像素点,高有1280个像素点
PPI英寸像素:Pixles per Inch 又称DPI(Dots-per-Inch),即像素密度,由对角线像素点除以屏幕大小获得,通常达到400PPI已经是非常高的屏幕密度了
PPI计算公式:√(宽2+长2) / 屏幕尺寸
假如一部手机的分辨率是1080×1920,屏幕大小是5英寸,通过宽1080和高1920,根据勾股定理,我们得出对角线的像素数大约是2203个,2203除以5,计算结果是440。440dpi就是屏幕密度
下表是Android手机的密度分类:
密度 | ldpi低分辨率 | mdpi中 | hdpi高 | xhdpi超高 | xxhdpi超超高分辨率 | xxxhdpi超超超高分辨率 |
---|---|---|---|---|---|---|
密度值 | 120 | 160 | 240 | 320 | 480 | 640 |
分辨率 | 240*320 | 320*480 | 480*800 | 120*1280 | 1080*1920 |
根据此表得到比例 ldpi:mdpi:hdpi:xhdpi:xxhdpi = 3:4:6:8:12
问题:假设在界面上绘制一个长度100px的线段,在分辨率为320*480的手机上,屏幕密度为160,分辨率为480 * 800屏幕上,屏幕密度为240,同样是100像素在两个不同分辨率屏幕上显示的长度就会不同,为了能在不同屏幕密度下得到相同长度的线段,我们使用dp为线段长度单位。
独立像素密度dp::density-independent pixel(密度无关像素)各种屏幕密度不同导致同样像素大小的长度,在不同密度的屏幕下的显示长度不同,相同长度的屏幕高度屏幕含有更多的像素点,android系统使用mdpi即密度值为160的屏幕作为标准,在这个屏幕上1px = 1dp,所以我们可以使用不同密度的比例计算对应屏幕的px与dp比例关系。
dp,px换算公式:px = dp * (dpi/160) dp = px / ( dpi /160 )
放大像素sp:用于TextView的字号,使用sp当用户字号设置发生改变时,字体可以自动调整。
默认情况下认为sp和dp一致是没有问题的,字体大小为“普通”,这时候dp和sp两个单位保持一致。但当修改了字体大小之后,以sp为单位的字体都会进行相应的缩放,所以谷歌推荐的字体单位的名字才叫做sp(scaled pixels)。
实际使用时可以封装转换工具类转换px , sp 和 dp
public class DisplayUtils{
//将px转换为dp
//scale 是密度因子,相当于(dpi /160 )
public static int px2dp(Context context,float pxValue){
final float scale = context.getResources().getDisplayMetrics().density;
//在代码中转换时最后加上了0.5f,Android官方文档给的解释是为了向上取整,这样转换也就更精确
return (int) (pxValue / scale + 0.5f);
}
//将dp转为px
public static int dp2px(Context,float dipValue){
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue * scale + 0.5f);
}
//dp转sp
public static int px2sp(Context context,float pxValue){
final float fontScale = context.getResources().getDisplayMetrics().scaleDensity;
return (int) ( pxValue / fontScale + 0.5f )
}
//dp转sp
public static int sp2[x(Context context,float spValue){
final float fontScale = context.getResources().getDisplayMetrics().scaleDensity;
return (int) ( pxValue * fontScale + 0.5f )
}
}