最近看了很多px转换dp,sp的贴子,看到了很多种方法
有通过安卓自带的工具类反向推导得出的工具类
public class UnitUtils {
//转换dip为px
public static int dp2px(Context context, int dip) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dip * scale + 0.5f * (dip >= 0 ? 1 : -1));
}
//转换px为dip
public static int px2dp(Context context, int px) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (px / scale + 0.5f * (px >= 0 ? 1 : -1));
}
public static int sp2px(Context context, float spValue) {
float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
public static int px2sp(Context context, float pxValue) {
float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
}
也有通过UI设计图片的宽高像素和屏幕尺寸,结合公式计算出来的
等等等等。。。。。。
最后通过测量控件高度打印日志,发现这些方法都不准确
可以这样算:
1、找UI问出作图时的宽和高的像素
2、通过代码获取设备的密度、dpi和宽
DisplayMetrics metrics = this.getResources().getDisplayMetrics();
float density = metrics.density; //屏幕密度
int dpi = metrics.densityDpi; //屏幕dpi
int widthPixels = metrics.widthPixels; //屏幕宽度
3、dp = (UI标的px / UI作图的宽度)* 设备的宽度 / 屏幕密度
举个例子: UI作图时是以1024*768为准做的图,我的设备是1920*1200的,屏幕密度是2.25,dpi是360
UI标注图里有个控件宽高都是100px,那么
100 / 768 * 1200 / 2.25 = 69.444
所以我就可以写69.444 dp
如果换个设备呢,换成2048*1536的,屏幕密度和dpi都换了,那69.444肯定就不合适了,改怎么办呢?不要急。。。
这就用到了最小屏幕宽度,最小屏幕宽度的单位是dp,那最小屏幕宽度怎么计算呢?
最小屏幕宽度 dp = 160 * 屏幕宽度 / dpi
还拿我上面那个例子来看,我的设备的最小屏幕宽度就是
160 * 1200 / 360 = 533.333 dp
所以我可以在res下面建个文件夹 values-sw533dp 或者 values-sw530dp,只要小于等于算出来的最小屏幕宽度就行,为什么要小于等于最小屏幕宽度呢?因为系统是从大到小。。。扫描吧。。如果建的文件夹是 values-sw550dp ,设备的只有553.333,达不到550,就会自动进入小一级的,如果已经是最小的了就会用系统默认的values文件夹内的内容
建好文件夹后在下面建个dimen.xml的文件,内容大致为
9.856sp
10.841sp
11.827sp
12.813sp
13.798sp
14.784sp
可以用我写好的方法:
int width = 1200;//ui作图的屏幕宽度
DisplayMetrics metrics = this.getResources().getDisplayMetrics();
float density = metrics.density; //设备密度
int dpi = metrics.densityDpi; //设备dpi
int widthPixels = metrics.widthPixels; //设备宽度
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("\n\n");
for (int px = 0; px <= 200; px += 2) {
String dp = px * 1.0 * widthPixels / width / density + "";
if (dp.indexOf(".") + 4 < dp.length()) {//保留3位小数
dp = dp.substring(0, dp.indexOf(".") + 4);
}
stringBuilder.append("").append(dp).append("dp \n");
}
stringBuilder.append(" ");
Log.e("tag", stringBuilder.toString());
打印出来结果是
0.0dp
0.888dp
1.777dp
2.666dp
3.555dp
4.444dp
5.333dp
6.222dp
7.111dp
8.0dp
8.888dp
9.777dp
10.666dp
11.555dp
12.444dp
13.333dp
14.222dp
15.111dp
16.0dp
16.888dp
17.777dp
18.666dp
19.555dp
20.444dp
21.333dp
22.222dp
23.111dp
24.0dp
24.888dp
25.777dp
26.666dp
27.555dp
28.444dp
29.333dp
30.222dp
31.111dp
32.0dp
32.888dp
33.777dp
34.666dp
35.555dp
36.444dp
37.333dp
38.222dp
39.111dp
40.0dp
40.888dp
41.777dp
42.666dp
43.555dp
44.444dp
45.333dp
46.222dp
47.111dp
48.0dp
48.888dp
49.777dp
50.666dp
51.555dp
52.444dp
53.333dp
54.222dp
55.111dp
56.0dp
56.888dp
57.777dp
58.666dp
59.555dp
60.444dp
61.333dp
62.222dp
63.111dp
64.0dp
64.888dp
65.777dp
66.666dp
67.555dp
68.444dp
69.333dp
70.222dp
71.111dp
72.0dp
72.888dp
73.777dp
74.666dp
75.555dp
76.444dp
77.333dp
78.222dp
79.111dp
80.0dp
80.888dp
81.777dp
82.666dp
83.555dp
84.444dp
85.333dp
86.222dp
87.111dp
88.0dp
88.888dp
到这里解决了px转换为dp的问题了,px转换为sp和这个方法一样,只是把dp改为sp就行了
做不同屏幕的适配就需要知道那个屏幕的宽度、屏幕密度、屏幕dpi,然后套用这个方法就行了。