默认显示的 Getter:显示!'已弃用。在 Java 中已弃用

问题描述 投票:0回答:11

我需要屏幕的宽度。但最近发现 Android

defaultDisplay
已弃用,并显示消息:

默认显示的 Getter:显示!'已弃用。在 Java 中已弃用

代码:

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

请提出替代方案。

android android-layout kotlin
11个回答
59
投票

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

33
投票

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)

参考:androidx.core源代码


如果您需要获取窗口的大小,新的 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()
        }
}

同步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()

参考:解绑 WindowManager | Android 开发者媒介


8
投票

此方法在 API 级别 30 中已弃用。

请使用

Context.getDisplay()
来代替。

已弃用的方法:getDefaultDisplay

新方法:getDisplay


6
投票

尝试这样的事情:


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

5
投票

我使用 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")

    }
}

如果你想在github上看到我的要点


3
投票

在 Api 级别 31 方法中

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

3
投票

以下代码可以应用于所有版本的 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();
    }

0
投票

任何想要用 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);
    }

0
投票

由于我必须去几个地方才能得到完整的答案,所以在一篇文章中: 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")

        }

    }
}

0
投票

这是一个 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) {
    }
}

-1
投票

这是我发现获得宽度的最简单方法

resources.displayMetrics.widthPixels
© www.soinside.com 2019 - 2024. All rights reserved.