如何相互转换 DP、PX、SP,尤其是 DP 和 SP?



我知道DPSPPX之间的区别。在搜索了这个话题之后,我发现没有什么让我完全满意的。也许这篇文章是重复的,但我仍然想知道从DPPX,DP到 SP,从 SP 到 PX,从 PX 到SP,从 SP 到 DPDPSP的公式是什么?我知道一些代码可以做到这一点,但它们并不完美。

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);
}

接受的答案缺少一些有用的转换。

SP 到 PX

float sp = 20;
float px = sp * getResources().getDisplayMetrics().scaledDensity;

float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());

PX 到 SP

float px = 70;
float sp = px / getResources().getDisplayMetrics().scaledDensity;

DP 到 PX

float dp = 20;
float px = dp * getResources().getDisplayMetrics().density;

float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());

PX 到 DP

float px = 70;
float dp = px / getResources().getDisplayMetrics().density;

笔记

  • 我在上面选择的浮点数(2070)是任意值。如果您愿意,可以插入不同的号码。
  • px是指像素。设备每英寸屏幕空间具有的像素数称为密度。
  • dp表示与密度无关的像素。也就是说,无论使用什么设备,实际大小都应该相同。例如,如果我将视图设置为100 dp宽,则它在新的高密度手机上的宽度将与旧的低密度手机上的宽度相同。(另一方面,如果我将宽度设置为100 px,则在低密度手机上会显得很大,而在高密度手机上会显得很小。密度以每英寸点数 (DPI) 为单位。公式是px = dp * density.因此,您只需乘以或除以密度即可在pxdp之间进行转换。
  • sp表示与比例无关的像素。它仅用于字体,而不是视图。它与dp类似,只是它也考虑了用户偏好。这种考虑到用户偏好的密度称为缩放密度。将TextView字体设置为30 sp,例如,将使文本在所有设备上通常看起来都是相同的物理大小。但是,您的祖母可能会在她的手机设置中一直将她的首选字体大小最大化,因此30 sp文本在她的手机上看起来会比在您的手机上更大。公式是px = sp * scaledDensity.
  • DP 和 SP 的含义
  • DP 到 SP 的转换通常没有用

要将维度转换为整数或像素,您需要使用">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文件中)

你可以写一个不需要contextresources的方法:

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);
}

以此类推,可以转换其他量。

根据 TypedValue#applyDimension 源代码并利用 Kotlin 扩展:

val 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()));
}

我知道,我的格式很残酷。可能不应该让它成为单行本。哦,好吧。

经过测试并且正在工作,但在稍微不同的上下文中,我必须对按钮的文本大小进行动画处理,其中初始文本大小单位可以是任何东西。

最新更新