做android开发的人都知道,在切图上跟UI设计师讨论dp/sp跟px的关系时都是很心累的。
一、dp、sp与px的定义
dp:英文全程为Density independent Pixels,设备无关像素,早期被叫做dip。
sp: 英文全程为Scale independent Pixel,缩放无关像素。
px: 英文全程为pixel,像素。
二、dp、sp与px的区别
讲这三者区别之前,首先应该说明什么是分辨率和像素密度。
分辨率:显示分辨率(屏幕分辨率)是屏幕图像的精密度,是指显示器所能显示的像素有多少。由
于屏幕上的点、线和面都是由像素组成的,显示器可显示的像素越多,画面就越精细,同样的屏幕
区域内能显示的信息也越多,所以分辨率是个非常重要的性能指标之一。可以把整个图像想象成是
一个大型的棋盘,而分辨率的表示方式就是所有经线和纬线交叉点的数目。显示分辨率一定的情况
下,显示屏越小图像越清晰,反之,显示屏大小固定时,显示分辨率越高图像越清晰。(摘自百度百科)
像素密度:英文全程为Dots Per Inch,每英寸所能显示的像素点即为像素密度,单位px/in。由于
通常我们提到的设备屏幕大小其实说的就是设备对角线的长度,所以通过厂商提供的分辨再结合勾
股定理即可算出像素密度。
px:在Android中不常用,因为一张100px*100px的图片在相同屏幕尺寸但分辨率不同的设备上显示的
大小是不一致的。通俗的讲就是在相同屏幕尺寸下,相同大小的图片在越大的分辨率下显示的越小。
dp:在Android中除了设置字体之外,需要明确指定尺寸的时候都是采用dp作为单位,因为在Android
系统中可以根据设备信息将dp转化为适合当前屏幕的px,从而达到适配的效果。
sp:在Android中主要用来设置字体,由于Android系统支持用户自定义字体大小(可以打开设备的设
置进入里面找字体大小一栏进行自定义),字体如果选择标准(普通/正常),那么1sp=1dp的。使用它
的原因跟使用dp的原因一致。
三、dp与px及sp与px的换算
这里提供两种换算方式,供你们参考。
第一种方式如下:
import android.content.Context;
import android.util.TypedValue;
public class DisplayNativeUtils {
/**
* dp转px
*
* @param context
* @return
*/
public static int dp2px(Context context, float dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, context.getResources().getDisplayMetrics());
}
/**
* sp转px
*
* @param context
* @return
*/
public static int sp2px(Context context, float spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spVal, context.getResources().getDisplayMetrics());
}
/**
* px转dp
*
* @param context
* @param pxVal
* @return
*/
public static float px2dp(Context context, float pxVal) {
final float scale = context.getResources().getDisplayMetrics().density;
return (pxVal / scale);
}
/**
* px转sp
*
* @param pxVal
* @return
*/
public static float px2sp(Context context, float pxVal) {
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
}
}
第二种方法如下所示:
import android.content.Context;
/**
* 避免丢失精度所以都加上了0.5f
*/
public class DisplayUtils {
/**
* 将px值转换为dip或dp值,保证尺寸大小不变
* @param context
* @param pxValue
* @return
*/
public static int px2dip(Context context, float pxValue){
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 将dip或dp值转换为px值,保证尺寸不变
* @param context
* @param dipValue
* @return
*/
public static int dip2px(Context context, float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
/**
* 将px值转换为sp值,保证文字大小不变
* @param context
* @param pxValue
* @return
*/
public static int px2sp(Context context, float pxValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
/**
* 将sp值转换为px值,保证文字大小不变
* @param context
* @param spValue
* @return
*/
public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
}
两种方法实质都是一样的,使用哪一种方法都可以。