我需要屏幕的宽度。但最近发现 Android
defaultDisplay
已弃用,并显示消息:
默认显示的 Getter:显示!'已弃用。在 Java 中已弃用
代码:
val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
return displayMetrics.widthPixels
请提出替代方案。
defaultDisplay
在 API 级别 30 (Android R) 及更高版本中被标记为已弃用。
这意味着,如果您的最低 SDK 配置低于 API 级别 30,则您应该同时使用旧的已弃用代码和新的推荐代码实现。
正确解决问题后,您可以使用 @Suppress("DEPRECATION") 来抑制警告
示例:Kotlin 解决方案
val outMetrics = DisplayMetrics()
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
val display = activity.display
display?.getRealMetrics(outMetrics)
} else {
@Suppress("DEPRECATION")
val display = activity.windowManager.defaultDisplay
@Suppress("DEPRECATION")
display.getMetrics(outMetrics)
}
WindowManager.getDefaultDisplay()
在 API 级别 30 中已弃用,取而代之的是需要最低 API 级别 30 的 Context.getDisplay()
方法。
androidx.core.content.ContextCompat
似乎没有提供任何向后兼容的getDisplay()
方法。
如果您只需要检索默认显示,而不是像其他答案建议的那样针对不同的 API 级别使用不同的方法,您可以使用
DisplayManager.getDisplay(Display.DEFAULT_DISPLAY)
方法(自 API 17 起支持)来实现相同的结果。
已弃用的代码:
val defaultDisplay = getSystemService<WindowManager>()?.defaultDisplay
新代码:
val defaultDisplay = getSystemService<DisplayManager>()?.getDisplay(Display.DEFAULT_DISPLAY)
如果您需要获取窗口的大小,新的 Jetpack WindowManager 库 为新旧平台版本中的新 Window Manager 功能(例如可折叠设备和 Chrome 操作系统)提供通用 API 接口。
dependencies {
implementation "androidx.window:window:1.0.0-beta02"
}
Jetpack WindowManager 提供两种方式来检索 WindowMetrics 信息:异步流或同步。
异步WindowMetrics流程:
WindowInfoRepository#currentWindowMetrics
获得库通知,无论此更改是否触发配置更改。
import androidx.window.layout.WindowInfoRepository
import androidx.window.layout.WindowInfoRepository.Companion.windowInfoRepository
import androidx.window.layout.WindowMetrics
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.flowWithLifecycle
lifecycleScope.launch(Dispatchers.Main) {
windowInfoRepository().currentWindowMetrics.flowWithLifecycle(lifecycle)
.collect { windowMetrics: WindowMetrics ->
val currentBounds = windowMetrics.bounds // E.g. [0 0 1350 1800]
val width = currentBounds.width()
val height = currentBounds.height()
}
}
lifecycleScope
和 flowWithLifecycle()
是 Jetpack Lifecycle 库的一部分。同步WindowMetrics:
在异步 API 难以处理的视图中编写代码时(例如 onMeasure
或在测试期间),请使用
WindowMetricsCalculator。
import androidx.window.layout.WindowMetricsCalculator
import androidx.window.layout.WindowMetrics
val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity)
val currentBounds = windowMetrics.bounds // E.g. [0 0 1350 1800]
val width = currentBounds.width()
val height = currentBounds.height()
尝试这样的事情:
private Display getDisplay(@NonNull WindowManager windowManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// This one (context) may or may not have a display associated with it, due to it being
// an application context
return getDisplayPostR();
} else {
return getDisplayPreR(windowManager);
}
}
@RequiresApi(api = Build.VERSION_CODES.R)
private Display getDisplayPostR() {
// We can't get the WindowManager by using the context we have, because that context is a
// application context, which isn't associated with any display. Instead, grab the default
// display, and create a DisplayContext, from which we can use the WindowManager or
// just get that Display from there.
//
// Note: the default display doesn't have to be the one where the app is on, however the
// getDisplays which returns a Display[] has a length of 1 on Pixel 3.
//
// This gets rid of the exception interrupting the onUserLogin() method
Display defaultDisplay = DisplayManagerCompat.getInstance(context).getDisplay(Display.DEFAULT_DISPLAY);
Context displayContext = context.createDisplayContext(defaultDisplay);
return displayContext.getDisplay();
}
@SuppressWarnings("deprecation")
private Display getDisplayPreR(@NonNull WindowManager windowManager) {
return windowManager.getDefaultDisplay();
}
或获取实际尺寸:
private Point getScreenResolution() {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (wm == null) {
return null;
}
Display display = getDisplay(wm);
return getSize(display, wm);
}
private Point getSize(Display forWhichDisplay, WindowManager windowManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return getSizePostR(windowManager);
} else {
return getSizePreR(forWhichDisplay);
}
}
@RequiresApi(api = Build.VERSION_CODES.R)
private Point getSizePostR(@NonNull WindowManager windowManager) {
WindowMetrics currentWindowMetrics = windowManager.getCurrentWindowMetrics();
Rect bounds = currentWindowMetrics.getBounds();
// Get the insets, such as titlebar and other decor views
WindowInsets windowInsets = currentWindowMetrics.getWindowInsets();
Insets insets = windowInsets.getInsets(WindowInsets.Type.navigationBars());
// If cutouts exist, get the max of what we already calculated and the system's safe insets
if (windowInsets.getDisplayCutout() != null) {
insets = Insets.max(
insets,
Insets.of(
windowInsets.getDisplayCutout().getSafeInsetLeft(),
windowInsets.getDisplayCutout().getSafeInsetTop(),
windowInsets.getDisplayCutout().getSafeInsetRight(),
windowInsets.getDisplayCutout().getSafeInsetBottom()
)
);
}
// Calculate the inset widths/heights
int insetsWidth = insets.right + insets.left;
int insetsHeight = insets.top + insets.bottom;
// Get the display width
int displayWidth = bounds.width() - insetsWidth;
int displayHeight = bounds.height() - insetsHeight;
return new Point(displayWidth, displayHeight);
}
// This was deprecated in API 30
@SuppressWarnings("deprecation")
private Point getSizePreR(Display display) {
Point size = new Point();
if (isRealDisplaySizeAvailable()) {
display.getRealSize(size);
} else {
display.getSize(size);
}
return size;
}
private static boolean isRealDisplaySizeAvailable() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
}
我使用 DisplayManagerCompat 在 android R-Above 上获取宽度和高度,并使用 DisplayMatrics 在其他 android 版本上获取它。
所以,这是我的代码(+ @Suppress("DEPRECATION") )
private fun screenValue() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val defaultDisplay =
DisplayManagerCompat.getInstance(this).getDisplay(Display.DEFAULT_DISPLAY)
val displayContext = createDisplayContext(defaultDisplay!!)
width = displayContext.resources.displayMetrics.widthPixels
height = displayContext.resources.displayMetrics.heightPixels
Log.e(tag, "width (ANDOIRD R/ABOVE): $width")
Log.e(tag, "height (ANDOIRD R/ABOVE) : $height")
} else {
val displayMetrics = DisplayMetrics()
@Suppress("DEPRECATION")
windowManager.defaultDisplay.getMetrics(displayMetrics)
height = displayMetrics.heightPixels
width = displayMetrics.widthPixels
Log.e(tag, "width (BOTTOM ANDROID R): $width")
Log.e(tag, "height (BOTTOM ANDROID R) : $height")
}
}
Display.getRealMetrics()
也已被弃用。推荐的方法是使用WindowManager#getCurrentWindowMetrics()
。我更喜欢以下方法来获取屏幕尺寸:
object ScreenSizeCompat {
private val api: Api =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) ApiLevel30()
else Api()
/**
* Returns screen size in pixels.
*/
fun getScreenSize(context: Context): Size = api.getScreenSize(context)
@Suppress("DEPRECATION")
private open class Api {
open fun getScreenSize(context: Context): Size {
val display = context.getSystemService(WindowManager::class.java).defaultDisplay
val metrics = if (display != null) {
DisplayMetrics().also { display.getRealMetrics(it) }
} else {
Resources.getSystem().displayMetrics
}
return Size(metrics.widthPixels, metrics.heightPixels)
}
}
@RequiresApi(Build.VERSION_CODES.R)
private class ApiLevel30 : Api() {
override fun getScreenSize(context: Context): Size {
val metrics: WindowMetrics = context.getSystemService(WindowManager::class.java).currentWindowMetrics
return Size(metrics.bounds.width(), metrics.bounds.height())
}
}
}
例如,要获取屏幕高度,请在
Activity
中使用它:
ScreenSizeCompat.getScreenSize(this).height
以下代码可以应用于所有版本的 Android(从 SDK 16 到 SDK 33+),没有任何弃用警告。
import android.hardware.display.DisplayManager;
import android.view.Display;
import android.util.DisplayMetrics;
import android.content.Context;
// ...
@NonNull
public static DisplayMetrics getDisplayMetrics(@NonNull Context context) {
DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
Display defaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
Context defaultDisplayContext = context.createDisplayContext(defaultDisplay);
return defaultDisplayContext.getResources().getDisplayMetrics();
}
任何想要用 Java 来做这件事的人都可以:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
Display display = this.getDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
display.getRealMetrics(displayMetrics);
float density = getResources().getDisplayMetrics().density;
float dpHeight = displayMetrics.heightPixels / density;
float dpWidth = displayMetrics.widthPixels / density;
Log.d(TAG, "OmesChecka R: "+"second width:"+dpWidth+"second h:"+dpHeight);
}else {
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics ();
display.getMetrics(outMetrics);
float density = getResources().getDisplayMetrics().density;
float dpHeight = outMetrics.heightPixels / density;
float dpWidth = outMetrics.widthPixels / density;
Log.d(TAG, "OmesChecka: "+"second width:"+dpWidth+"second h:"+dpHeight);
}
由于我必须去几个地方才能得到完整的答案,所以在一篇文章中: getDefaultDisplay 方法从 Android API 30 (Android 11) 开始已被弃用,但仍然有效。
即便如此,因为它已被贬值,您应该使用适用于 Android 11 的新方法,并仍实现适用于 Android 10 或更早版本的旧方法。
这是带有注释的代码:(要运行此代码,您需要在 build.gradle 中启用 viewBinding (因为我没有使用 findViewByID)、一个名为“main_activity”的顶级布局的 Activity_main.xml、一个名为“的按钮视图”计算按钮”,以及三个名为“android_version”、“screen_height”和“screen_width”的文本视图。)
package com.example.test
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.WindowManager
import com.example.test.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.calculateButton.setOnClickListener { calcScreenSize() }
}
private fun calcScreenSize() { //All in one function to calculate and display screen size in pixels
val metrics = DisplayMetrics()
var width: Int = 0
var height: Int = 0
val version = android.os.Build.VERSION.SDK_INT //Check android version. Returns API # ie 29 (Android 10), 30 (Android 11)
if (version >= android.os.Build.VERSION_CODES.R) { //If API is version 30 (Android 11) or greater, use the new method for getting width/height
binding.androidVersion.setText("Android API Version: $version")
binding.mainActivity.display?.getRealMetrics(metrics) //New method
width = metrics.widthPixels
height = metrics.heightPixels
binding.screenHeight.setText("Height: $height") //Display Width and Height in Text Views
binding.screenWidth.setText("Width: $width")
} else {
binding.androidVersion.setText("Android API Version: $version") //If API is less than version 30 (ie 29 (Android 10)), use the old method for getting width/height
@Suppress("DEPRECATION") //Suppress the "Deprecation" warning
windowManager.defaultDisplay.getMetrics(metrics) //Old method
width = metrics.widthPixels
height = metrics.heightPixels
binding.screenHeight.setText("Height: $height") //Display Width and Height in Text Views
binding.screenWidth.setText("Width: $width")
}
}
}
这是一个 Java 解决方案,尝试尽可能减少代码、导入和进一步折旧的方法。我在游戏中留下了潜在的设备插图,以保持视图尽可能大。但是,注释的代码会缩短插图的宽度和高度。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
WindowMetrics windowMetrics = ((Activity) context).getWindowManager().getCurrentWindowMetrics();
//Insets insets = windowMetrics.getWindowInsets().getInsetsIgnoringVisibility(WindowInsets.Type.systemBars());
screenWidth = windowMetrics.getBounds().width();// - insets.left - insets.right;
screenHeight = windowMetrics.getBounds().height();// - insets.top - insets.bottom;
} else {
Display display = ((Activity) context).getWindowManager().getDefaultDisplay();//getDefaultDisplay depreciated getMetrics() depreciated
Point size = new Point();
display.getSize(size);
screenWidth = size.x;
screenHeight = size.y;
try {
Point realSize = new Point();
Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize);
screenWidth = realSize.x;
screenHeight = realSize.y;
} catch (Exception ignored) {
}
}
这是我发现获得宽度的最简单方法
resources.displayMetrics.widthPixels