创建活动时如何获取DisplayCutout高度?

时间:2018-09-05 16:00:39

标签: android android-layout surfaceview android-9.0-pie display-cutouts

我有一个全屏SurfaceView(纵向)的游戏,线程在表面连续渲染。

SurfaceView已初始化onCreate,其大小由屏幕的宽度和高度(以像素为单位)确定。

创建后,将其设置为游戏活动的内容视图(无XML定义):

Bitmap frameBuffer = Bitmap.createBitmap(screenWidth, screenHeight, Config.ARGB_8888);

MySurfaceView renderView = new MySurfaceView(this, frameBuffer);

this.setContentView(renderView);

问题是,屏幕高度不包括“显示切口”(对于具有它们的设备),并且比允许的绘制屏幕高,这是因为renderView放置在切口区域下方,并且不使用它进行渲染。

我试图找到真实的screen height - display cutout height,以便使帧缓冲区具有该高度。

您是否知道是否可以获取显示切口区域高度onCreate,就像我们能够获取导航/状态栏高度一样。以下是返回导航栏高度的代码段:

Resources resources = getResources();
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
    int navigationBarHeight = resources.getDimensionPixelSize(resourceId);
}

谢谢您的帮助!

---更新---

我将尝试进一步阐明问题:

1)onCreate创建了一个全屏肖像SurfaceView,其尺寸为屏幕的宽度和高度(无XML)

2)为API级别> 19(KitKat)启用了沉浸模式

3)屏幕宽度和高度由Display.getSize()或Display.getRealSize()决定,具体取决于API级别

4)在具有顶部显示切口的设备上,视图自动置于切口下方,底部内容被切除,这就是问题

5)我想获取显示切口onCreate的高度,以便可以将SurfaceView的高度创建为screenHeight - displayCutoutHeight

6)问题归结为找到显示切口的高度。

5 个答案:

答案 0 :(得分:2)

WindowInsets.getDisplayCutout()返回DisplayCutout对象(如果存在)。

要获取显示切口的边界矩形,可以使用

DisplayCutout.getBoundingRects()

它将为您提供屏幕上所有显示切口(非功能区域)的Rect列表。

为了获得每个显示切口的高度,

Rect.height()

这也可能返回负值,因此请确保采用高度模量。

有关显示抠图支持的更多信息,请参见以下链接:

android:windowLayoutInDisplayCutoutMode

DisplayCutout

layoutInDisplayCutoutMode

WindowInsets

WindowInsets.getDisplayCutout()

答案 1 :(得分:2)

似乎无法在onCreate中获取WindowInsets对象。您的Activity必须先附加到窗口。因此,您的选择是:

1。

override fun onAttachedToWindow() {
    val cutout = window.decorView.rootWindowInsets.displayCutout
}

2。

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    contentView?.setOnApplyWindowInsetsListener { _, insets ->
        val cutout = insets.displayCutout
        return@setOnApplyWindowInsetsListener insets
    }
}

答案 2 :(得分:1)

这是onCreate()中的方法:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {

    drumRoll1Button.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {

                DisplayCutout displayCutout = drumRoll1Button.getRootWindowInsets().getDisplayCutout();
                if (displayCutout!=null) {
                    displayCutoutLengthPx = displayCutout.getSafeInsetLeft();
                }
            Log.v(LOG_TAG,"displayCutoutLengthPx:"+displayCutoutLengthPx);
        }
    });
}

如果您处于纵向模式(原始问题正在询问),请交换屏幕上的任何视图(对于drumRoll1Button)和getSafeInsetTop()(对于getSafeInsetLeft())。此示例适用于风景。

答案 3 :(得分:1)

对Roman答案的修改(上面)对我有用:

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        Log.i("Chicken", "cutout: " + getWindow().getDecorView().getRootWindowInsets().getDisplayCutout());
   }

答案 4 :(得分:0)

停止读取Android私有资源,并停止调用getRealSize()。只需调用getSize(),您返回的值将很好使用。