私は、密度に依存しないピクセルとその逆のピクセルの可変量を計算しようとしています。
この式(px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160));
はゼロで除算されるため、小さなデバイスでは機能しません。
これは私のdpからpxの式です:
px = (int)(dp * (displayMetrics.densityDpi / 160));
誰かが私にいくつかの指針を与えることができますか?
私は、密度に依存しないピクセルとその逆のピクセルの可変量を計算しようとしています。
この式(px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160));
はゼロで除算されるため、小さなデバイスでは機能しません。
これは私のdpからpxの式です:
px = (int)(dp * (displayMetrics.densityDpi / 160));
誰かが私にいくつかの指針を与えることができますか?
回答:
注:上記で広く使用されているソリューションはに基づいていdisplayMetrics.density
ます。ただし、ドキュメントでは、この値は丸められた値であり、画面の「バケット」で使用されると説明されています。例えば。私のNexus 10では2を返します。実際の値は298dpi(実数)/ 160dpi(デフォルト)= 1.8625です。
要件によっては、次のようにして実現できる正確な変換が必要になる場合があります。
[編集]もちろんこれは画面バケットに基づいているため、Androidの内部dpユニットと混合することを意図していません。異なるデバイスで同じ実サイズをレンダリングするユニットが必要な場合にこれを使用します。
dpをピクセルに変換:
public int dpToPx(int dp) {
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
ピクセルをdpに変換します。
public int pxToDp(int px) {
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
return Math.round(px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
xdpiとydpiのプロパティがあるので、区別した方がいいかもしれませんが、これらの値が大きく異なる正気なディスプレイは想像できません。
以下の計算式で解決しました。他の人々がそれから利益を得ることができますように。
dpからpx:
displayMetrics = context.getResources().getDisplayMetrics();
return (int)((dp * displayMetrics.density) + 0.5);
pxからdpへ:
displayMetrics = context.getResources().getDisplayMetrics();
return (int) ((px/displayMetrics.density)+0.5);
pxからdpへ:
int valueInpx = ...;
int valueInDp= (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, valueInpx , getResources()
.getDisplayMetrics());
typedValue.applyDimension( TypedValue.COMPLEX_UNIT_PX, valueInDp , getResources() .getDisplayMetrics());
、PXからDPへ、これも最良の回答です
applyDimension
ピクセルのみを生成します。android.googlesource.com/platform/frameworks/base/+/refs/heads/…を参照してくださいCOMPLEX_UNIT_PX
。変換は行われません。
dp
。ソースコードを見ると、ケースTypedValue.COMPLEX_UNIT_DIP
でvalue * metrics.density
は、実際に必要な場所が返されますvalue * metrics.density
。それでは、あなたはvalueInDp`をgetting`ていることではありませんdp
用valueInPx
の中でpx
。
value / metrics.density
DPからPixel:
private int dpToPx(int dp)
{
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
ピクセルからDP:
private int pxToDp(int px)
{
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
これがお役に立てば幸いです。
displayMetrics.xdpi
どのデバイスでも異なるものを使用しているためです。悲しいことに、この間違った答えはさらに賛成票が最も多くなります。
private fun dpToPx(dp: Int) = (dp * Resources.getSystem().displayMetrics.density).toInt()
この機能を使用
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
px = dp * (dpi / 160)
dp = px * (160 / dpi)
(displayMetrics.densityDpi / 160)
-この部分は、小さなデバイスでは0を取得できます。そこで計算されます。たとえば120/160
、両方の値がintであり、結果は0になります(int) (px/0)
。
ほとんどの場合、変換関数は頻繁に呼び出されます。メモ化を追加することで最適化できます。そのため、関数が呼び出されるたびに計算されるわけではありません。
計算された値を格納するHashMapを宣言しましょう。
private static Map<Float, Float> pxCache = new HashMap<>();
ピクセル値を計算する関数:
public static float calculateDpToPixel(float dp, Context context) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return px;
}
HashMapから値を返し、以前の値の記録を維持するメモ化関数。
メモ化は、Javaでさまざまな方法で実装できます。Java 7の場合:
public static float convertDpToPixel(float dp, final Context context) {
Float f = pxCache.get(dp);
if (f == null) {
synchronized (pxCache) {
f = calculateDpToPixel(dp, context);
pxCache.put(dp, f);
}
}
return f;
}
Java 8はLambda関数をサポートしています:
public static float convertDpToPixel(float dp, final Context context) {
pxCache.computeIfAbsent(dp, y ->calculateDpToPixel(dp,context));
}
ありがとう。
以下の機能は、さまざまなデバイスでうまく機能しました。
https://gist.github.com/laaptu/7867851から取得
public static float convertPixelsToDp(float px){
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return Math.round(dp);
}
public static float convertDpToPixel(float dp){
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return Math.round(px);
}
DP、SP、インチ、ミリメートル、ポイント、ピクセルを互いに異なる画面密度で相互に変換するためのオンライン計算機を探しているなら、これは私が知っている最も完全なツールです。
// Decimal / Floatの観点から取得
public static float convertPixelsToDp(float px, Context context) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return Math.round(dp);
}
public static float convertDpToPixel(float dp, Context context) {
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return Math.round(px);
}
// for getting in terms of Integer
private int convertPxToDp(int px, Context context) {
Resources resources = context.getResources();
return Math.round(px / (resources.getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
private int convertDpToPx(int dp, Context context) {
Resources resources = context.getResources();
return Math.round(dp * (resources.getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
________________________________________________________________________________
public static float convertPixelsToDp(float px){
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return Math.round(dp);
}
public static float convertDpToPixel(float dp){
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return Math.round(px);
}
private int convertDpToPx(int dp){
return Math.round(dp*(getResources().getDisplayMetrics().xdpi/DisplayMetrics.DENSITY_DEFAULT));
}
private int convertPxToDp(int px){
return Math.round(px/(Resources.getSystem().getDisplayMetrics().xdpi/DisplayMetrics.DENSITY_DEFAULT));
}
上記で受け入れられた答えは完全に正確ではありません。Androidのソースコードを調べて得られた情報によると:
Resources.getDimension()
およびgetDimensionPixelOffset()
/ getDimensionPixelSize()
は、前者が戻りfloat
、後者の2つはint
適切に丸められた同じ値を返すという点でのみ異なります。それらすべての場合、戻り値は生のピクセル単位です。
3つすべての関数は、を呼び出しResources.getValue()
て変換することによって実装され、とをTypedValue
呼び出して取得します。TypedValue.complexToDimension()
TypedValue.complexToDimensionPixelOffset()
TypedValue.complexToDimensionPixelSize()
したがって、XMLソースで指定された単位と一緒に「生の」値を取得する場合Resources.getValue()
は、TypedValue
クラスのメソッドを呼び出して使用します。
上記のct_robsの回答のバリエーション。整数を使用している場合、0による除算を回避するだけでなく、小さなデバイスでも使用可能な結果を生成します。
最大精度の除算を含む整数計算では、切り捨ての影響を減らすために、除算の前に最初に乗算します。
px = dp * dpi / 160
dp = px * 160 / dpi
5 * 120 = 600 / 160 = 3
の代わりに
5 * (120 / 160 = 0) = 0
あなたが丸められた結果が欲しいならこれをしてください
px = (10 * dp * dpi / 160 + 5) / 10
dp = (10 * px * 160 / dpi + 5) / 10
10 * 5 * 120 = 6000 / 160 = 37 + 5 = 42 / 10 = 4