Abrufen der Bildschirmbreite auf API-Ebene 30 (Android 11): getDefaultDisplay() und getMetrics() sind jetzt veraltet. Was sollten wir stattdessen verwenden?
Lesezeit: 6 Minuten
Dennis
Ich berechne derzeit die Bildschirmbreite wie folgt:
public static int getScreenWidth(@NonNull Context context) {
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.widthPixels;
}
Da diese 2 Funktionen (getDefaultDisplay() und getMetrics()) sind jetzt veraltet, was sollten wir stattdessen verwenden?
Welche Größe willst du genau berechnen? Soll es Statusleisten, Navigationsleisten, Ausschnitte enthalten? Ich habe die in der Dokumentation vorgeschlagenen Ersetzungen ausprobiert und keine Kombination von Optionen gefunden, die dieselbe Höhe wie dieser Code erzeugen, was für mich darauf hindeutet, dass dieser Code wahrscheinlich keine besonders nützliche Metrik berechnet.
–Ryan M ♦
14. August 2020 um 8:39 Uhr
context.getDisplay() ist die Alternative zu context.getWindowManager().getDefaultDisplay()
– Jashanpreet singh Chakkal
13. April 2021 um 4:01 Uhr
@JashanChakkal, aber getMetrics() von getDisplay() ist immer noch veraltet.
– Chitgoks
16. Oktober 2021 um 12:53 Uhr
Für die Berechnung der Bildschirmbreite abzüglich aller Systembalken sollte dies funktionieren:
public static int getScreenWidth(@NonNull Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();
Insets insets = windowMetrics.getWindowInsets()
.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars());
return windowMetrics.getBounds().width() - insets.left - insets.right;
} else {
DisplayMetrics displayMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.widthPixels;
}
}
Beachten Sie, dass dies nicht der Fall ist exakt dasselbe: Das Testen mit der Höhe führt zu anderen Ergebnissen, und ich war nicht in der Lage, die Funktionalität der alten API mit der neuen API zu replizieren (teilweise aufgrund des Verhaltens der alten API, das etwas schwierig zu verstehen ist und nicht immer das, was Sie tun wollen, daher seine Abwertung). In der Praxis sollte es aber als generische Bildschirmbreite für viele Dinge gut genug sein.
Ich habe die Dokumentation gelesen und denke auch, dass dies so sein sollte. Sie haben Recht.
– Dennis
14. August 2020 um 9:22 Uhr
Ihre neue und veraltete Methode gibt unterschiedliche Ergebnisse für Pixel 4 im Querformat zurück
– Benutzer924
10. Dezember 2020 um 17:43 Uhr
Ich denke, wir sollten auch verwenden window.decorView.rootWindowInsets?.displayCutout (safeInsetLeft und safeInsetRight), das sind nicht alle 0einige > 0
– Benutzer924
10. Dezember 2020 um 17:52 Uhr
Es gibt ein Problem bei der Verwendung von windowMetrics.getWindowInsets(), wenn der Bildschirm zwangsweise vom Hochformat ins Querformat gedreht wird, geben Insets.left und insets.right immer 0 zurück.
– CodierungBruceLee
27. September 2021 um 12:47 Uhr
und Dichte für R+?
– Benutzer924
24. Dezember 2021 um 10:45 Uhr
Vincent Joshua Tigas
@RequiresApi(20)
inline val Fragment.windowHeight: Int
get() {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val metrics = requireActivity().windowManager.currentWindowMetrics
val insets = metrics.windowInsets.getInsets(WindowInsets.Type.systemBars())
metrics.bounds.height() - insets.bottom - insets.top
} else {
val view = requireActivity().window.decorView
val insets = WindowInsetsCompat.toWindowInsetsCompat(view.rootWindowInsets, view).getInsets(WindowInsetsCompat.Type.systemBars())
resources.displayMetrics.heightPixels - insets.bottom - insets.top
}
}
@RequiresApi(20)
inline val Fragment.windowWidth: Int
get() {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val metrics = requireActivity().windowManager.currentWindowMetrics
val insets = metrics.windowInsets.getInsets(WindowInsets.Type.systemBars())
metrics.bounds.width() - insets.left - insets.right
} else {
val view = requireActivity().window.decorView
val insets = WindowInsetsCompat.toWindowInsetsCompat(view.rootWindowInsets, view).getInsets(WindowInsetsCompat.Type.systemBars())
resources.displayMetrics.widthPixels - insets.left - insets.right
}
}
Dies erfordert androidx.core Ausführung 1.5.x
Dein RequiresApi falsch ist, erfordert es API-Level 23.
– Xam
25. August 2021 um 21:22 Uhr
Wenn 2022 dasselbe Problem auftritt, gibt es eine neuere Jetpack-Bibliothek, um dies über die verschiedenen API-Versionen hinweg zu handhaben.
import androidx.window.layout.WindowMetrics;
import androidx.window.layout.WindowMetricsCalculator;
WindowMetrics windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity);
final int height = windowMetrics.getBounds().height();
final int width = windowMetrics.getBounds().width();
Eine Einschränkung, auf die ich auch gestoßen bin, ist die einschließlich androidx.window Am Ende zog ich Zehntausende von Bibliotheksmethoden ein, die mich über das DEX 64k-Methodenlimit brachten, also musste ich herausfinden, wie diese mithilfe der R8/Proguard-Einstellungen optimiert werden, aber das ist ein anderes Problem.
val windowMetrics = requireActivity().windowManager.currentWindowMetrics
val displayMetrics = resources.displayMetrics
val pxHeight = windowMetrics.bounds.height()
val pxWidth = windowMetrics.bounds.width()
val density = displayMetrics.density
val dpHeight = pxHeight/density
val dpWidth = pxWidth/density
hat
Ich denke, ich habe erfolgreich gleichwertige Methoden (Verbesserung von @RyanM) implementiert, um eine zu verwerfen.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Deprecated older method for comparison.
DisplayMetrics outMetrics = new DisplayMetrics();
getDisplay().getMetrics(outMetrics);
Log.d("Upto API-29", String.format(
"(width, height) = (%d, %d)", outMetrics.widthPixels, outMetrics.heightPixels
));
// Newer methods.
Log.d("API-30+", String.format(
"(width, height) = (%d, %d)", getScreenWidth(this), getScreenHeight(this)
));
}
public static int getScreenWidth(@NonNull Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();
Rect bounds = windowMetrics.getBounds();
Insets insets = windowMetrics.getWindowInsets().getInsetsIgnoringVisibility(
WindowInsets.Type.systemBars()
);
if (activity.getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE
&& activity.getResources().getConfiguration().smallestScreenWidthDp < 600
) { // landscape and phone
int navigationBarSize = insets.right + insets.left;
return bounds.width() - navigationBarSize;
} else { // portrait or tablet
return bounds.width();
}
} else {
DisplayMetrics outMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
}
public static int getScreenHeight(@NonNull Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();
Rect bounds = windowMetrics.getBounds();
Insets insets = windowMetrics.getWindowInsets().getInsetsIgnoringVisibility(
WindowInsets.Type.systemBars()
);
if (activity.getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE
&& activity.getResources().getConfiguration().smallestScreenWidthDp < 600
) { // landscape and phone
return bounds.height();
} else { // portrait or tablet
int navigationBarSize = insets.bottom;
return bounds.height() - navigationBarSize;
}
} else {
DisplayMetrics outMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.heightPixels;
}
}
Die Punkte sind
Die Höhe von SystemBar ist nicht in der Höhe von Windowbound enthalten. Wir sollten nur die Höhe der Navigationsleiste ausschließen (es sei denn, sie befindet sich im Querformat auf dem Telefongerät).
Im Querformat auf dem Telefongerät sollten wir die Größe der Navigationsleiste von der Breite der Fensterbegrenzung ausschließen.
Die meisten Antworten hier verwenden windowManager.getCurrentWindowMetrics() Methode, um die Bildschirmgröße zu erhalten. Dies gibt jedoch nicht die tatsächliche Bildschirmgröße (physisches Gerät) an. Wenn sich der Bildschirm im geteilten Modus befindet, nimmt die Anwendung nur einen Teil des Bildschirms ein und zeigt diese Größe anstelle der vollen Bildschirmgröße an.
Um also die Vollbildgröße zu erhalten, wird die Verwendung empfohlen windowManager.getMaximumWindowMetrics() Methode.
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
WindowMetrics metrics = windowManager.getMaximumWindowMetrics();
Rect bounds = metrics.getBounds();
int width = bounds.width();
int height = bounds.height();
Ravi Makwana
Sie können verwenden
Context.getDisplay() Anstatt von getDefaultDisplay()
display.getRealMatrix(displayMetrics) Anstatt von display.getMetrics(displayMetrics)
display.getRealMatrix gibt die volle Größe Ihres Bildschirms zurück (einschließlich der Größe der Statusleiste und der Navigationsleiste)
– Benutzer924
10. Dezember 2020 um 17:20 Uhr
14320500cookie-checkAbrufen der Bildschirmbreite auf API-Ebene 30 (Android 11): getDefaultDisplay() und getMetrics() sind jetzt veraltet. Was sollten wir stattdessen verwenden?yes
Welche Größe willst du genau berechnen? Soll es Statusleisten, Navigationsleisten, Ausschnitte enthalten? Ich habe die in der Dokumentation vorgeschlagenen Ersetzungen ausprobiert und keine Kombination von Optionen gefunden, die dieselbe Höhe wie dieser Code erzeugen, was für mich darauf hindeutet, dass dieser Code wahrscheinlich keine besonders nützliche Metrik berechnet.
–Ryan M
♦
14. August 2020 um 8:39 Uhr
context.getDisplay() ist die Alternative zu context.getWindowManager().getDefaultDisplay()
– Jashanpreet singh Chakkal
13. April 2021 um 4:01 Uhr
@JashanChakkal, aber getMetrics() von getDisplay() ist immer noch veraltet.
– Chitgoks
16. Oktober 2021 um 12:53 Uhr