13

我有一个带有全屏SurfaceView(纵向)的游戏和在表面上连续呈现的线程。

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

创建后,它被设置为 Game Activity 的内容视图(无 XML 定义):

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

MySurfaceView renderView = new MySurfaceView(this, frameBuffer);

this.setContentView(renderView);

问题是,屏幕高度不包括 Display Cutouts(对于具有它们的设备)并且比允许的绘图屏幕高,因为 renderView 放置在 cutout 区域下方并且不使用它进行渲染。

我试图找到真实的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)我想得到 Display Cutout 的高度onCreate,这样我就可以将 SurfaceView 的高度创建为screenHeight - displayCutoutHeight

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

4

4 回答 4

6

似乎没有办法WindowInsets在 onCreate 中获取对象。您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
    }
}
于 2019-04-17T10:17:13.223 回答
3

对 Roman 的回答(上图)的修改对我有用:

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        Log.i("Chicken", "cutout: " + getWindow().getDecorView().getRootWindowInsets().getDisplayCutout());
   }
于 2019-12-12T15:07:13.177 回答
3

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

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

DisplayCutout.getBoundingRects()

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

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

Rect.height()

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

有关显示切口支持的更多信息,请参阅以下链接:

安卓:windowLayoutInDisplayCutoutMode

显示切口

layoutInDisplayCutoutMode

窗口插图

WindowInsets.getDisplayCutout()

于 2018-09-05T16:26:03.297 回答
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())进行交换,这是原始问题所要求的。此示例适用于景观。

于 2019-08-02T15:47:53.953 回答