Ich habe meine Anwendung mit der in Pixel angegebenen Höhe und Breite für ein Pantech-Gerät mit einer Auflösung von 480 x 800 erstellt.
Ich muss Höhe und Breite für ein G1-Gerät konvertieren. Ich dachte, die Umwandlung in dp würde das Problem lösen und die gleiche Lösung für beide Geräte bieten.
Gibt es eine einfache Möglichkeit, Pixel in dp umzuwandeln? Irgendwelche Vorschläge?
// Converts 14 dip into its equivalent px
float dip = 14f;
Resources r = getResources();
float px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dip,
r.getDisplayMetrics()
);
/**
* 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);
}
Setzen Sie sich vorzugsweise in eine Util.Java-Klasse
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;
}
float density = context.getResources().getDisplayMetrics().density;
float px = someDpValue * density;
float dp = somePxValue / density;
density
ist gleich
.75
auf ldpi
(120
dpi) 1.0
auf mdpi
(160
dpi; Basislinie)1.5
auf hdpi
(240
dpi)2.0
auf xhdpi
(320
dpi) 3.0
auf xxhdpi
(480
dpi) 4.0
auf xxxhdpi
(640
dpi) Verwenden Sie diesen Online-Konverter , um mit dpi-Werten herumzuspielen.
EDIT: Anscheinend gibt es keine 1: 1-Beziehung zwischen dpi
bucket und density
. Es sieht so aus, als hätte der Nexus 5X
, der xxhdpi
ist, einen density
-Wert von 2.625
(anstelle von 3
). Überzeugen Sie sich selbst in den Device Metrics .
Wenn Sie die Dimensionen XML verwenden können, ist das sehr einfach!
In Ihrem res/values/dimens.xml
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="thumbnail_height">120dp</dimen>
...
...
</resources>
Dann in deinem Java:
getResources().getDimensionPixelSize(R.dimen.thumbnail_height);
Laut dem Android Development Guide:
px = dp * (dpi / 160)
Oft müssen Sie dies jedoch auch in umgekehrter Reihenfolge ausführen, wenn Sie ein in Pixeln angegebenes Design erhalten. So:
dp = px / (dpi / 160)
Wenn Sie sich auf einem 240-dpi-Gerät befinden, beträgt dieses Verhältnis 1,5 (wie zuvor angegeben). Das bedeutet, dass ein 60px-Symbol in der Anwendung 40dp entspricht.
Sie können diese .. ohne Kontext verwenden
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);
}
Wie @Stan erwähnt .. kann dieser Ansatz Probleme verursachen, wenn die Dichte des Systems geändert wird. Seien Sie sich also dessen bewusst!
Persönlich verwende ich Context, um das zu tun.
Ohne Context
elegante statische Methoden:
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);
}
Für DP to Pixel
Erstellen Sie einen Wert in dimens.xml
<dimen name="textSize">20dp</dimen>
Holen Sie sich diesen Wert in pixel
als:
int sizeInPixel = context.getResources().getDimensionPixelSize(R.dimen.textSize);
Sie können daher den folgenden Formulator verwenden, um die richtige Pixelanzahl aus einer in dp angegebenen Dimension zu berechnen
public int convertToPx(int dp) {
// Get the screen's density scale
final float scale = getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
return (int) (dp * scale + 0.5f);
}
In Android SDK gibt es ein Standardprogramm: http://developer.Android.com/reference/Android/util/TypedValue.html
float resultPix = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics())
Für alle, die Kotlin verwenden:
val Int.toPx: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
val Int.toDp: Int
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
Verwendungszweck:
64.toPx
32.toDp
Dies sollte Ihnen die Umwandlung von dp in Pixel ermöglichen:
public static int dpToPx(int dp)
{
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
Dies sollte Ihnen die Konvertierungspixel in dp geben:
public static int pxToDp(int px)
{
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
Wenn Sie die Dimension innerhalb von values / dimen haben, ist es wahrscheinlich am besten, die Dimension direkt von der getDimension () -Methode zu erhalten. Sie gibt die in Pixelwert bereits konvertierte Dimension zurück.
context.getResources().getDimension(R.dimen.my_dimension)
Nur um das besser zu erklären,
getDimension(int resourceId)
gibt die bereits in Pixel A FLOAT konvertierte Dimension zurück.
getDimensionPixelSize(int resourceId)
wird das gleiche zurückgeben, aber auf int abgeschnitten, also AS AN INTEGER.
Siehe Android Referenz
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)
}
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);
}
public static int dp2px(Resources resource, int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,resource.getDisplayMetrics());
}
public static float px2dp(Resources resource, float px) {
return (float) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px,resource.getDisplayMetrics());
}
die Ressource ist context.getResources ().
die Verwendung von Kotlin-Extension macht es besser
fun Int.toPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt()
fun Int.toDp(context: Context): Int = (this / context.resources.displayMetrics.density).toInt()
UPDATE:
Da displayMetrics
Teil von global shared Resources ist, können wir Resources.getSystem()
verwenden.
fun Int.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()
fun Int.toDp(): Int = (this / Resources.getSystem().displayMetrics.density).toInt()
so was:
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;
}
}
abhängig von Kontext, Rückgabewerte, statische Methode
Wenn Sie eine leistungskritische Anwendung entwickeln, berücksichtigen Sie bitte die folgende optimierte Klasse:
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;
}
}
float scaleValue = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) (dps * scaleValue + 0.5f);
So funktioniert es für mich:
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int h = displaymetrics.heightPixels;
float d = displaymetrics.density;
int heightInPixels=(int) (h/d);
Sie können dasselbe für die Breite tun.
Eleganter Ansatz mit Kotlins Erweiterungsfunktion
/**
* 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()
Verwendungszweck:
println("16 dp in pixel: ${16.dpToPx}")
println("16 px in dp: ${16.pxToDp}")
Sie sollten dp genauso wie Pixel verwenden. Das ist alles, was sie sind. Anzeige unabhängiger Pixel. Verwenden Sie dieselben Zahlen wie auf einem Bildschirm mit mittlerer Dichte, und die Größe wird auf einem Bildschirm mit hoher Dichte magisch korrekt sein.
Es klingt jedoch so, als ob Sie die fill_parent -Option in Ihrem Layoutentwurf benötigen. Verwenden Sie fill_parent, wenn Ihre Ansicht oder Ihr Steuerelement auf die gesamte verbleibende Größe im übergeordneten Container erweitert werden soll.
um Pixel in dp umzuwandeln, verwenden Sie den TypedValue .
Wie in der Dokumentation erwähnt: Container für einen dynamisch typisierten Datenwert.
und verwende die applyDimension -Methode:
public static float applyDimension (int unit, float value, DisplayMetrics metrics)
dabei wird ein entpackter komplexer Datenwert, der eine Dimension enthält, in den endgültigen Gleitkommawert wie folgt konvertiert:
Resources resource = getResources();
float dp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 69, resource.getDisplayMetrics());
Hoffentlich hilft das .
Viele tolle Lösungen oben. Die beste Lösung, die ich gefunden habe, ist das Design von Google:
PX
und DP
sind unterschiedlich, aber ähnlich.
DP
ist die Auflösung, wenn Sie nur die physische Größe des Bildschirms berücksichtigen. Wenn Sie DP
verwenden, wird Ihr Layout auf andere Bildschirme ähnlicher Größe mit unterschiedlichen pixel
-Dichten skaliert.
Gelegentlich möchten Sie jedoch pixels
, und wenn Sie mit Dimensionen im Code arbeiten, haben Sie immer echte pixels
zu tun, sofern Sie diese nicht konvertieren.
Also auf einem Android-Gerät, normaler hdpi
-Bildschirm, 800x480 is 533x320
in DP
(ich glaube). Um DP
in pixels /1.5
umzuwandeln, um *1.5
zurück zu konvertieren. Dies gilt nur für die eine Bildschirmgröße und dpi
, sie ändert sich je nach Design. Unsere Künstler geben mir jedoch pixels
und ich konvertiere mit der obigen 1.5
-Gleichung in DP
.
Wenn Sie Integer Werte wollen, wird der Float bei Verwendung von Math.round () auf die nächste Ganzzahl gerundet.
public static int pxFromDp(final float dp) {
return Math.round(dp * Resources.getSystem().getDisplayMetrics().density);
}
Das funktioniert für mich (C #):
int pixels = (int)((dp) * Resources.System.DisplayMetrics.Density + 0.5f);
kotlin
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;
}
Für den Java-Code von React Native gibt es bereits eine util-Klasse:
import com.facebook.react.uimanager.PixelUtil;
float dp = PixelUtil.toDIPFromPixel(somePixelValue);
Die beste Antwort kommt vom Android Framework selbst: Verwende einfach diese Gleichheit ...
public static int dpToPixels(final DisplayMetrics display_metrics, final float dps) {
final float scale = display_metrics.density;
return (int) (dps * scale + 0.5f);
}
(konvertiert dp in px)
Für Xamarin.Android
float DpToPixel(float dp)
{
var resources = Context.Resources;
var metrics = resources.DisplayMetrics;
return dp * ((float)metrics.DensityDpi / (int)DisplayMetricsDensity.Default);
}
Wenn Sie einen benutzerdefinierten Renderer erstellen, ist dies nicht statisch