我了解 DP, SP 和 PX 之间的区别。但是在搜索这个主题后,我没有找到完全满意的答案。也许这篇文章已经有了重复内容,但我仍想知道从DP 到 PX,DP 到 SP,从 SP 到 PX,从 PX 到 SP,从 SP 到 DP,从 DP 到 SP 的转换公式是什么?我了解了一些代码,但它们并不完美。
DP 转 PX:
public static int dpToPx(float dp, Context context) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
}
SP 转 PX:
public static int spToPx(float sp, Context context) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics());
}
DP 转 SP:
public static int dpToSp(float dp, Context context) {
return (int) (dpToPx(dp, context) / context.getResources().getDisplayMetrics().scaledDensity);
}
被接受的答案缺少了一些有用的转换。
float sp = 20;
float px = sp * getResources().getDisplayMetrics().scaledDensity;
或者float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
float px = 70;
float sp = px / getResources().getDisplayMetrics().scaledDensity;
float dp = 20;
float px = dp * getResources().getDisplayMetrics().density;
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
float px = 70;
float dp = px / getResources().getDisplayMetrics().density;
20
和 70
)是任意值。如果你喜欢,你可以输入不同的数字。px
指的是像素。设备每英寸屏幕空间有多少像素称为密度。dp
代表密度无关像素。也就是说,无论使用什么设备,实际大小应该相同。例如,如果我将一个视图设置为 100 dp
宽,它在新的高密度手机和旧的低密度手机上的宽度都将是相同的。(另一方面,如果我将宽度设置为 100 px
,则在低密度手机上显示会很大,在高密度手机上则会很小。)密度以每英寸点数(DPI)为单位进行测量。公式为 px = dp * density
。因此,只需乘以或除以密度即可在 px
和 dp
之间转换。sp
意味着比例独立像素。它仅用于字体,而不是视图。它类似于 dp
,但还考虑了用户的偏好。考虑到用户偏好的密度称为缩放密度。例如,将 TextView
字体大小设置为 30 sp
,则文本通常在所有设备上看起来物理大小相同。但是,您的祖母可能已经将她的首选字体大小设置为最大,在她的手机设置中,因此 30 sp
文本在她的手机上看起来比在你的手机上更大。公式为 px = sp * scaledDensity
。scaledDensity
现已过时。Android 14现在进行非线性字体缩放,因此您应该使用TypedValue.applyDimension
。 - Remc4将尺寸转换为整数或像素需要使用 "getDimensionPixelSize(R.dimen.your_dp_value)" 函数,例如...
在 dimens.xml 文件中设置一个值
<dimen name="padding_10">10dp</dimen>
int sizeInPixel = context.getResources().getDimensionPixelSize(R.dimen.padding_10);
对于 kotlin
,我创建了一个扩展函数:
fun Number.spToPx(context: Context) = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, this.toFloat(), context.resources.displayMetrics).toInt()
16.spToPx(context)
或16.5.spToPx(context)
。KotlinExtensions.kt
文件中)您可以编写一种不需要context
或resources
的方法:
public static int dpToPx(int dp) {
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
public static int spToPx(int sp) {
return (int) (sp * Resources.getSystem().getDisplayMetrics().scaledDensity);
}
类比地,其他量也可以进行转换。
Resources.getSystem()
未针对当前屏幕进行配置,因此无法使用尺寸单位。 - timgoval Float.toSp get() = this * Resources.getSystem().displayMetrics.scaledDensity
其他扩展来自 链接
val Float.toPx get() = this * Resources.getSystem().displayMetrics.density
val Float.toDp get() = this / Resources.getSystem().displayMetrics.density
对我来说,只需反转applyDimension()即可,因此这个解决方案适用于所有单位。
public static int unApplyDimension(int unit,float value){
return (int)( b.getTextSize()/TypedValue.applyDimension(
b.getTextSizeUnit(),1,
getApplicationContext().getResources().getDisplayMetrics()));
}
我知道我的格式很糟糕。也许不应该把它变成一行代码。不过没关系。
已经测试并且可以工作,但是在稍微不同的情况下,我必须对按钮的文本大小进行动画处理,其中初始文本大小单位可以是任何东西。