在没有上下文的情况下将 dp 转换为 px

Converting dp to px without Context

有一种非常简洁的方法可以在没有上下文的情况下将 dp 转换为 px,它是这样的:

public static int dpToPx(int dp) {
    float density = Resources.getSystem().getDisplayMetrics().density;
    return Math.round((float) dp * density);
}

Google GitHub page 上的每个 Google 示例中,他们都使用以下方法:

public static int convertDpToPixel(Context ctx, int dp) {
    float density = ctx.getResources().getDisplayMetrics().density;
    return Math.round((float) dp * density);
}

那么第一种方法有问题吗?对我来说,它在我所有的应用程序中都运行良好,但我想知道在某些情况下它可能会失败吗?

is there some case where it might fail?

有,有!

Android 支持不同的屏幕,例如您可以使用 Chromecast 投射应用程序或通过其他方式连接到不同的屏幕。在这种情况下,这些值将无法正确转换到其他屏幕。

来自 documentation for Resources.getSystem():

Return a global shared Resources object that provides access to only system resources (no application resources), and is not configured for the current screen (can not use dimension units, does not change based on orientation, etc).

这里有一个小的 Kotlin 扩展函数:

private fun Context.dpToPx(dp: Float): Float {
    val density = this.resources.displayMetrics.density
    return (dp * density).roundToInt().toFloat()
}

根据之前的回答,这些扩展应该有效:

val Int.dp get() = this / (Resources.getSystem().displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
val Float.dp get() = this / (Resources.getSystem().displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)

val Int.px get() = this * Resources.getSystem().displayMetrics.density
val Float.px get() = this * Resources.getSystem().displayMetrics.density

用法:

val dpValue = 2.dp
val pxFromDpValue = 2.px

重要:

我不确定 Resources.getSystem() 是否能正确处理方向变化。