简体   繁体   English

默认显示的吸气剂:显示。 已弃用。 在 Java 中已弃用

[英]Getter for defaultDisplay: Display!' is deprecated. Deprecated in Java

I need the width of the screen.我需要屏幕的宽度。 But recently found Android defaultDisplay deprecacted with message:但最近发现 Android defaultDisplay deprecated with message:

Getter for defaultDisplay: Display.'默认显示的吸气剂:显示。 is deprecated.已弃用。 Deprecated in Java在 Java 中已弃用

Code:代码:

val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
return displayMetrics.widthPixels

Please suggest an alternative.请提出替代方案。

defaultDisplay was marked as deprecated in API level 30 (Android R) and above. defaultDisplay在 API 级别 30 (Android R) 及更高版本中被标记为已弃用。 This means if you have a minimum SDK configuration below API level 30, you should have both implementations with the old deprecated code and the new recommended code.这意味着如果您的最低 SDK 配置低于 API 级别 30,您应该同时使用旧的弃用代码和新的推荐代码实现。

After fixing the problem correctly you can use @Suppress("DEPRECATION") to suppress warnings正确解决问题后,您可以使用 @Suppress("DEPRECATION") 来抑制警告

Example: Kotlin solution示例: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)
    }

This method was deprecated in API level 30.此方法在 API 级别 30 中已弃用。

Use Context.getDisplay() instead.请改用Context.getDisplay()

Deprecated method: getDefaultDisplay不推荐使用的方法: getDefaultDisplay

New Method: getDisplay新方法: getDisplay

WindowManager.getDefaultDisplay() was deprecated in API level 30 in favour of Context.getDisplay() method which requires minium API level 30. WindowManager.getDefaultDisplay()在 API 级别 30 中已弃用,取而代之的是Context.getDisplay()方法,该方法需要最低 API 级别 30。

At the moment, androidx.core.content.ContextCompat doesn't seem to offer any backwards compatible getDisplay() method.目前, androidx.core.content.ContextCompat似乎没有提供任何向后兼容的getDisplay()方法。

If you only need to retrieve the default display, instead of using different methods for different API levels as other answers suggest, you can you DisplayManager.getDisplay(Display.DEFAULT_DISPLAY) method (supported since API 17) to achieve the same result.如果您只需要检索默认显示,而不是像其他答案建议的那样对不同的 API 级别使用不同的方法,您可以使用DisplayManager.getDisplay(Display.DEFAULT_DISPLAY)方法(自 API 17 起支持)来实现相同的结果。

Deprecated code:不推荐使用的代码:

val windowManager = getSystemService<WindowManager>()!!
val defaultDisplay = windowManager.defaultDisplay

New code:新代码:

val displayManager = getSystemService<DisplayManager>()!!
val defaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY)

Ref: androidx.core source code参考: androidx.core 源代码


If what you need is to get the size of the Window, the new Jetpack WindowManager library provides a common API surface for new Window Manager features (eg foldable devices and Chrome OS) throughout old and new platform versions.如果您需要获得 Window 的大小,新的Jetpack WindowManager 库为新的 Window 管理器功能和新平台的 Chrome OS 和新平台版本提供了一个通用的 API 表面。

  • WindowManager.getCurrentWindowMetrics() : returns the WindowMetrics according to the current system state. WindowManager.getCurrentWindowMetrics() :根据当前系统state返回WindowMetrics The metrics describe the size of the area the window would occupy with MATCH_PARENT width and height and any combination of flags that would allow the window to extend behind display cutouts.这些指标描述了 window 将占用的区域大小,其中MATCH_PARENT宽度和高度以及允许 window 延伸到显示切口后面的任何标志组合。
  • WindowManager.getMaximumWindowMetrics() : returns the largest WindowMetrics an app may expect in the current system state. WindowManager.getMaximumWindowMetrics() :返回应用程序在当前系统 state 中可能期望的最大WindowMetrics The value of this is based on the largest potential windowing state of the system.此值基于系统的最大潜在窗口 state。 For example, for activities in multi-window mode the metrics returned are based on what the bounds would be if the user expanded the window to cover the entire screen.例如,对于多窗口模式下的活动,返回的指标基于用户扩展 window 以覆盖整个屏幕时的边界。

Sample code ( ref ):示例代码( 参考):

dependencies {
    implementation "androidx.window:window:1.0.0-beta01"
}

import androidx.window.WindowManager

val vm = WindowManager(context)
vm.currentWindowMetrics.bounds // E.g. [0 0 1350 1800]
vm.maximumWindowMetrics.bounds 

I use DisplayCompatManager to get width and height on android R-Above and use DisplayMatrics to get it on other android version.我使用DisplayCompatManager在 android R-Above 上获取宽度和高度,并使用DisplayMatrics在其他 android 版本上获取它。

So, this is my code ( + @Suppress("DEPRECATION") )所以,这是我的代码( + @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")

    }
}

If you want see my gist in github 如果您想在 github 中查看我的要点

Anyone looking to do it in java here you go:任何想要在 java 中做这件事的人都在这里 go:

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);
    }

Since I had to go to several places to get the complete answer, here it is in one post: getDefaultDisplay method is depreciated as of Android API 30 (Android 11), but still works.因为我不得不 go 到几个地方才能获得完整的答案,所以它在一篇文章中:getDefaultDisplay 方法自 Android API 起已贬值,但 Android 仍然有效。

Even so, because it's depreciated you should use the new method for Android 11, and still implement the old method for Android 10 or earlier.即便如此,由于它已贬值,您应该使用 Android 11 的新方法,并且仍然执行 Android 10 或更早版本的旧方法。

Here's the code, with comments: (To run this you need viewBinding enabled in your build.gradle (since I'm not using findViewByID), an activity_main.xml with your top level layout named "main_activity", a button view named "calculate_button", and three text views named "android_version", "screen_height" and "screen_width".)这是带有注释的代码:(要运行此代码,您需要在 build.gradle 中启用 viewBinding(因为我没有使用 findViewByID),一个 activity_main.xml,您的顶级布局名为“main_activity”,一个名为“calculate_button”的按钮视图,以及三个名为“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")

        }

    }
}

Instead of doing that, do this and save the hassle of writing more code.与其这样做,不如这样做并省去编写更多代码的麻烦。

val dialog = super.onCreateDialog(savedInstanceState)
dialog.setOnShowListener {
    val bottomSheetDialog = it as BottomSheetDialog
    val parentLayout =
        bottomSheetDialog.findViewById<View>(R.id.design_bottom_sheet)
    parentLayout?.let { bottomSheet ->
        val behaviour = BottomSheetBehavior.from(bottomSheet)
        val layoutParams = bottomSheet.layoutParams
        layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT
        bottomSheet.layoutParams = layoutParams
        behaviour.state = BottomSheetBehavior.STATE_EXPANDED
    }
}
return dialog

Try something like this:尝试这样的事情:


    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();
    }

or to get the actual size:或获取实际尺寸:

    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;
    }

In Api Level 31 method Display.getRealMetrics() was deprecated as well.在 Api 级别 31 方法Display.getRealMetrics()也被弃用。 The recommended way is to use WindowManager#getCurrentWindowMetrics() .推荐的方法是使用WindowManager#getCurrentWindowMetrics() I prefer the following approach to get screen size:我更喜欢以下方法来获取屏幕尺寸:

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())
        }
    }
}

And to get, for example, screen height use it in Activity :例如,要获得屏幕高度,请在Activity中使用它:

ScreenSizeCompat.getScreenSize(this).height

Here is a java solution attempting the least amount of code, imports, and further depreciated methods as possible.这是一个 java 解决方案,它尝试尽可能少的代码、导入和进一步折旧的方法。 I leave potential device insets in my game to keep the view as large as possible.我在我的游戏中保留了潜在的设备插图,以使视图尽可能大。 However, the commented code will shorten width and height for insets.但是,注释代码将缩短插图的宽度和高度。

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) {
    }
}

I need the width of the screen.我需要屏幕的宽度。 But recently found Android defaultDisplay deprecacted with message:但最近发现 Android defaultDisplay deprecated with message:

Getter for defaultDisplay: Display.'默认显示的吸气剂:显示。 is deprecated.已弃用。 Deprecated in Java在 Java 中已弃用

Code:代码:

val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
return displayMetrics.heightPixels

Please suggest an alternative.请提出替代方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM