Android und programmgesteuertes Einstellen von Breite und Höhe in dp-Einheiten

304

Ich mache:

button.setLayoutParams(new GridView.LayoutParams(65, 65));

Gemäß den Dokumenten sind die Einheiten für die Breite und Höhe (beide 65 oben) "Pixel". Wie erzwingen Sie, dass dies geräteunabhängige Pixel oder "dp" sind?

SK9
quelle

Antworten:

541

Sie müssen es mithilfe des Skalierungsfaktors der Anzeige von dps in Pixel konvertieren.

final float scale = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) (dps * scale + 0.5f);
Robby Pond
quelle
111
Die korrekte Konvertierung ist (int) (dps * scale + 0.5f). Dies ist die Formel, die wir im gesamten Framework verwenden.
Romain Guy
8
Die Formel befindet sich in den Dokumenten. Weitere
Informationen finden
34
@RomainGuy, können Sie der API eine Dienstprogrammfunktion hinzufügen, von der aus konvertiert werden dpsoll px? Vielen Dank.
AlikElzin-Kilaka
3
Was ist DPS hier? Ich bekomme den Fehler "DPS kann nicht in eine Variable aufgelöst werden". Welche Art von "dps" muss deklariert werden?
Deepak
5
Die Variable "dps" ist der Eingabewert, den Sie konvertieren möchten.
Robby Pond
233

Ich weiß, dass dies eine alte Frage ist, aber ich habe einen viel saubereren Weg gefunden, diese Konvertierung durchzuführen.

Java

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65, getResources().getDisplayMetrics());

Kotlin

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65f, resources.displayMetrics)
drspaceboo
quelle
8
Gut gemacht, um herauszufinden, wie das geht. Ich bin kein Fan davon, eine Formel an mehreren Stellen zu wiederholen! Vielen Dank.
Darrenp
2
Wenn nicht, dann erstellen Sie eine Funktion mit der Formel
Sayka
1
@ Kenobi Es führt für Sie die Konvertierung von DP nach PX durch. Das 65obige ist der DP-Wert, den Sie in PX konvertieren möchten
drspaceboo
7
Dies sollte die akzeptierte Antwort sein, nicht die aktuelle, bei der diese Zahl (0,5) magisch von
nirgendwoher kommt
1
@ Johny19 Die 0.5 ist keine Magie. Es geht nur darum, eine Gleitkommazahl auf die nächste Ganzzahl zu runden, anstatt sie abzuschneiden. Weitere Informationen finden Sie in meinem Kommentar zur Antwort von Robby Pond.
MarredCheese
38

Wenn Sie sich Ihre Anforderungen ansehen, gibt es auch eine alternative Lösung. Anscheinend kennen Sie die Dimensionen in dp zur Kompilierungszeit, sodass Sie den Ressourcen einen Dimen-Eintrag hinzufügen können. Anschließend können Sie den Bemaßungseintrag abfragen und er wird bei diesem Aufruf automatisch in Pixel konvertiert:

final float inPixels= mActivity.getResources().getDimension(R.dimen.dimen_entry_in_dp);

Und Ihre dimension.xml wird haben:

<dimen name="dimen_entry_in_dp">72dp</dimen>

Wenn Sie diese Idee erweitern, können Sie einfach den Wert 1dp oder 1sp als Maßeintrag speichern, den Wert abfragen und als Multiplikator verwenden. Mit diesem Ansatz isolieren Sie den Code aus dem mathematischen Material und verlassen sich bei der Durchführung der Berechnungen auf die Bibliothek.

Weinstock
quelle
Beachten Sie, dass der Rückgabewert tatsächlich ein int ist, sodass er in einen Float umgewandelt wird.
CorayThan
Dies ist eine schlechte Antwort, weil es Fahrpreis ist, dynamisch zu sein
Johny19
37

Der einfachste Weg (und funktioniert sogar ab API 1), der getestet wurde, ist:

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

Aus Dokumentationen:

Rufen Sie eine Dimension für eine bestimmte Ressourcen-ID ab, um sie als Größe in Rohpixeln zu verwenden. Dies ist dasselbe wie getDimension (int), außer dass der zurückgegebene Wert zur Verwendung als Größe in ganzzahlige Pixel konvertiert wird. Bei einer Größenkonvertierung wird der Basiswert gerundet und sichergestellt, dass ein Basiswert ungleich Null mindestens ein Pixel groß ist.

Ja, es rundet den Wert ab, aber es ist nicht sehr schlecht (nur bei ungeraden Werten auf hdpi- und ldpi-Geräten muss ein kleiner Wert hinzugefügt werden, wenn ldpi nicht sehr häufig ist). Ich habe in einem xxhdpi-Gerät getestet, das 4dp in 16 (Pixel) konvertiert, und das ist wahr.

David
quelle