将像素转换为dp

我已经创建了我的应用程序,其高度和宽度以像素为单位,用于分辨率为480x800的Pantech设备。

我需要转换G1设备的高度和宽度。
我认为将其转换为dp将解决问题,并为两个设备提供相同的解决方案。

有没有简单的方法将像素转换为dp?
有什么建议吗?

841412 次浏览

你应该像使用像素一样使用dp。这就是它们的全部;显示独立的像素。使用与中密度屏幕相同的数字,并且在高密度屏幕上的大小将神奇地正确。

但是,听起来您需要的是布局设计中的fill_parent选项。当您希望您的视图或控件扩展到父容器中的所有剩余大小时,请使用fill_parent。

Java代码:

// Converts 14 dip into its equivalent pxfloat dip = 14f;Resources r = getResources();float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dip,r.getDisplayMetrics());

静态编程语言代码:

 val dip = 14fval r: Resources = resourcesval px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dip,r.displayMetrics)

静态编程语言扩展:

val Number.toPx get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,this.toFloat(),Resources.getSystem().displayMetrics)

PXDP不同但相似。

当您只考虑屏幕的物理尺寸时,DP是分辨率。当您使用DP时,它会将您的布局缩放到具有不同pixel密度的其他类似大小的屏幕。

有时你实际上想要pixels,当你在代码中处理维度时,你总是在处理真正的pixels,除非你转换它们。

所以在安卓设备上,普通大小的hdpi屏幕,800x480 is 533x320DP中(我相信)。要将DP转换为pixels /1.5,转换回*1.5。这仅适用于一个屏幕尺寸和dpi,它会根据设计而变化。我们的艺术家给了我pixels,我用上面的1.5等式转换为DP

根据Android开发指南:

px = dp * (dpi / 160)

但是,当您收到以像素表示的设计时,通常会希望以另一种方式执行此操作。所以:

dp = px / (dpi / 160)

如果您使用的是240dpi设备,则该比率为1.5(如前所述),因此这意味着应用程序中的60px图标等于40dp。

float density = context.getResources().getDisplayMetrics().density;float px = someDpValue * density;float dp = somePxValue / density;

density等于

  • .75 onldpi120 dpi)
  • 1.0mdpi160 dpi;基线)
  • 1.5 onhdpi240 dpi)
  • 2.0 onxhdpi320 dpi)
  • 3.0 onxxhdpi480 dpi)
  • 4.0 onxxxhdpi640 dpi)

使用这个在线转换器来处理dpi值。

编辑:dpidensity之间似乎没有1:1的关系。看起来Nexus 5Xxxhdpidensity的值是2.625(而不是3)。在设备指标中亲自查看。

/*** This method converts dp unit to equivalent pixels, depending on device density.** @param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels* @param context Context to get resources and device specific display metrics* @return A float value to represent px equivalent to dp depending on device density*/public static float convertDpToPixel(float dp, Context context){return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);}
/*** This method converts device specific pixels to density independent pixels.** @param px A value in px (pixels) unit. Which we need to convert into db* @param context Context to get resources and device specific display metrics* @return A float value to represent dp equivalent to px value*/public static float convertPixelsToDp(float px, Context context){return px / ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);}

因此,您可以使用以下公式从dp中指定的维度计算正确的像素量

public int convertToPx(int dp) {// Get the screen's density scalefinal float scale = getResources().getDisplayMetrics().density;// Convert the dps to pixels, based on density scalereturn (int) (dp * scale + 0.5f);}

最好是Util.java

public static float dpFromPx(final Context context, final float px) {return px / context.getResources().getDisplayMetrics().density;}
public static float pxFromDp(final Context context, final float dp) {return dp * context.getResources().getDisplayMetrics().density;}

如果您开发性能关键型应用程序,请考虑以下优化类:

public final class DimensionUtils {
private static boolean isInitialised = false;private static float pixelsPerOneDp;
// Suppress default constructor for noninstantiability.private DimensionUtils() {throw new AssertionError();}
private static void initialise(View view) {pixelsPerOneDp = view.getResources().getDisplayMetrics().densityDpi / 160f;isInitialised = true;}
public static float pxToDp(View view, float px) {if (!isInitialised) {initialise(view);}
return px / pixelsPerOneDp;}
public static float dpToPx(View view, float dp) {if (!isInitialised) {initialise(view);}
return dp * pixelsPerOneDp;}}

这就是它对我的工作方式:

DisplayMetrics displaymetrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);int  h = displaymetrics.heightPixels;float  d = displaymetrics.density;int heightInPixels=(int) (h/d);

你可以对宽度做同样的事情。

没有Context,优雅的静态方法:

public static int dpToPx(int dp){return (int) (dp * Resources.getSystem().getDisplayMetrics().density);}
public static int pxToDp(int px){return (int) (px / Resources.getSystem().getDisplayMetrics().density);}

如果您可以使用维度XML,那就非常简单了!

在你的res/values/dimens.xml

<?xml version="1.0" encoding="utf-8"?><resources><dimen name="thumbnail_height">120dp</dimen>......</resources>

在你的Java:

getResources().getDimensionPixelSize(R.dimen.thumbnail_height);

要将Pixels转换为dp,请使用类型值

如留档所述:用于动态类型数据值的容器。

并使用应用维度方法:

public static float applyDimension (int unit, float value, DisplayMetrics metrics)

它将保存维度的未打包复杂数据值转换为其最终浮点值,如下所示:

Resources resource = getResources();float dp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 69, resource.getDisplayMetrics());

希望有帮助。

android SDK中有一个默认的util:http://developer.android.com/reference/android/util/TypedValue.html

float resultPix = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics())

像这样:

public class ScreenUtils {
public static float dpToPx(Context context, float dp) {if (context == null) {return -1;}return dp * context.getResources().getDisplayMetrics().density;}
public static float pxToDp(Context context, float px) {if (context == null) {return -1;}return px / context.getResources().getDisplayMetrics().density;}}

依赖于Context,返回浮点值,静态方法

来自:https://github.com/Trinea/android-common/blob/master/src/cn/trinea/android/common/util/ScreenUtils.java#L15

如果您在值/dimen中包含维度,可能最好的方法是直接从getDimension()方法获取维度,它会返回已转换为像素值的维度。

context.getResources().getDimension(R.dimen.my_dimension)

为了更好地解释这一点,

getDimension(int resourceId)

将返回已转换为像素AS A FLOAT的维度。

getDimensionPixelSize(int resourceId)

将返回相同但截断为int,因此AS AN整数。

android参考

float scaleValue = getContext().getResources().getDisplayMetrics().density;int pixels = (int) (dps * scaleValue + 0.5f);

对于DP to Pixel

dimens.xml中创建一个值

<dimen name="textSize">20dp</dimen>

pixel中获取该值为:

int sizeInPixel = context.getResources().getDimensionPixelSize(R.dimen.textSize);

要转换dp to px,此代码可能会有所帮助:

public static int dpToPx(Context context, int dp) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (dp * scale + 0.5f);}

将dp转换为像素

public static int dp2px(Resources resource, int dp) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,resource.getDisplayMetrics());}

将像素转换为dp。

public static float px2dp(Resources resource, float px)  {return (float)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,px,resource.getDisplayMetrics());}

其中资源context.getResources()。

上面有很多很棒的解决方案。然而,我找到的最好的解决方案是谷歌的设计:

https://design.google.com/devices/

密度

这对我有用(C#):

int pixels = (int)((dp) * Resources.System.DisplayMetrics.Density + 0.5f);

你可以用这个…没有上下文

public static int pxToDp(int px) {return (int) (px / Resources.getSystem().getDisplayMetrics().density);}
public static int dpToPx(int dp) {return (int) (dp * Resources.getSystem().getDisplayMetrics().density);}

正如@Stan提到的…如果系统改变密度,使用这种方法可能会导致问题。所以要注意这一点!

就我个人而言,我正在使用Context来做到这一点。这只是我想与您分享的另一种方法

使用kotlin的扩展函数更优雅的方法

/*** Converts dp to pixel*/val Int.dpToPx: Int get() = (this * Resources.getSystem().displayMetrics.density).toInt()
/*** Converts pixel to dp*/val Int.pxToDp: Int get() = (this / Resources.getSystem().displayMetrics.density).toInt()

用法:

println("16 dp in pixel: ${16.dpToPx}")println("16 px in dp: ${16.pxToDp}")

对于任何使用静态编程语言的人:

val Int.toPx: Intget() = (this * Resources.getSystem().displayMetrics.density).toInt()
val Int.toDp: Intget() = (this / Resources.getSystem().displayMetrics.density).toInt()

用法:

64.toPx32.toDp

如果需要整数值,则使用Math.round()将浮点数四舍五入到最接近的整数。

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

这应该给你转换dp到像素:

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

这应该给你转换像素到dp:

public static int pxToDp(int px){return (int) (px / Resources.getSystem().getDisplayMetrics().density);}
((MyviewHolder) holder).videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(final MediaPlayer mediaPlayer) {mediaPlayer.setLooping(true);((MyviewHolder) holder).spinnerView.setVisibility(View.GONE);mediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {@Overridepublic void onVideoSizeChanged(MediaPlayer mp, int width, int height) {/** add media controller*/MediaController controller = new MediaController(mContext);float density = mContext.getResources().getDisplayMetrics().density;float px = 55 * density;// float dp = somePxValue / density;controller.setPadding(0, 0, 0, (int) (px));((MyviewHolder) holder).videoView.setMediaController(controller);}});}});

对于Xamarin. Android

float DpToPixel(float dp){var resources = Context.Resources;var metrics = resources.DisplayMetrics;return dp * ((float)metrics.DensityDpi / (int)DisplayMetricsDensity.Default);}

当您制作自定义渲染器时,使其成为非静态是必要的

静态编程语言

fun convertDpToPixel(dp: Float, context: Context): Float {return dp * (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)}
fun convertPixelsToDp(px: Float, context: Context): Float {return px / (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)}

Java

public static float convertDpToPixel(float dp, Context context) {return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);}
public static float convertPixelsToDp(float px, Context context) {return px / ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);}

静态编程语言:

fun spToPx(ctx: Context, sp: Float): Float {return sp * ctx.resources.displayMetrics.scaledDensity}
fun pxToDp(context: Context, px: Float): Float {return px / context.resources.displayMetrics.density}
fun dpToPx(context: Context, dp: Float): Float {return dp * context.resources.displayMetrics.density}

Java:

public static float spToPx(Context ctx,float sp){return sp * ctx.getResources().getDisplayMetrics().scaledDensity;}
public static float pxToDp(final Context context, final float px) {return px / context.getResources().getDisplayMetrics().density;}
public static float dpToPx(final Context context, final float dp) {return dp * context.getResources().getDisplayMetrics().density;}

使用kotlin扩展使其更好

fun Int.toPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt()
fun Int.toDp(context: Context): Int = (this / context.resources.displayMetrics.density).toInt()

更新:

因为displayMetrics全球共享资源的一部分,我们可以使用Resources.getSystem()

val Float.toPx get() = this * Resources.getSystem().displayMetrics.density    
val Float.toDp get() = this / Resources.getSystem().displayMetrics.density    

    
val Int.toPx get() = (this * Resources.getSystem().displayMetrics.density).toInt()    
val Int.toDp get() = (this / Resources.getSystem().displayMetrics.density).toInt()    

PS:根据@EpicPandaForce的评论:

您不应该为此使用Resources.getSystem(),因为它不处理可折叠和ChromeOS设备。

最好的答案来自Android框架本身:只需使用这种平等…

public static int dpToPixels(final DisplayMetrics display_metrics, final float dps) {final float scale = display_metrics.density;return (int) (dps * scale + 0.5f);}

(将dp转换为px)

private fun toDP(context: Context,value: Int): Int {return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,value.toFloat(),context.resources.displayMetrics).toInt()}

开发者文档提供了关于如何将dp单位转换为像素单位的答案:

在某些情况下,您需要在dp中表达尺寸,然后将它们转换为像素。dp单位到屏幕像素的转换是简单:

px=dp*(dpi/160)

提供了两个代码示例,一个Java示例和一个静态编程语言示例。

// The gesture threshold expressed in dpprivate static final float GESTURE_THRESHOLD_DP = 16.0f;
// Get the screen's density scalefinal float scale = getResources().getDisplayMetrics().density;// Convert the dps to pixels, based on density scalemGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);
// Use mGestureThreshold as a distance in pixels...

静态编程语言示例:

// The gesture threshold expressed in dpprivate const val GESTURE_THRESHOLD_DP = 16.0f...private var mGestureThreshold: Int = 0...override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
// Get the screen's density scaleval scale: Float = resources.displayMetrics.density// Convert the dps to pixels, based on density scalemGestureThreshold = (GESTURE_THRESHOLD_DP * scale + 0.5f).toInt()
// Use mGestureThreshold as a distance in pixels...}

我从Java示例创建的Java方法效果很好:

/*** Convert dp units to pixel units* https://developer.android.com/training/multiscreen/screendensities#dips-pels** @param dip input size in density independent pixels*            https://developer.android.com/training/multiscreen/screendensities#TaskUseDP** @return pixels*/private int dpToPixels(final float dip) {// Get the screen's density scalefinal float scale = this.getResources().getDisplayMetrics().density;// Convert the dps to pixels, based on density scalefinal int pix = Math.round(dip * scale + 0.5f);    
if (BuildConfig.DEBUG) {Log.i(DrawingView.TAG, MessageFormat.format("Converted: {0} dip to {1} pixels",dip, pix));}    
return pix;}

这个问题的其他几个答案提供了与这个答案相似的代码,但是在其他答案中没有足够的支持留档让我知道其他答案是否正确。接受的答案也与这个答案不同。我认为开发者留档清楚地说明了Java的解决方案。

合成中也有一个解决方案。合成中的密度为设备无关像素(dp)和像素之间的转换提供了一行解决方案

val sizeInPx = with(LocalDensity.current) { 16.dp.toPx() }