Как получить высоту DisplayCutout при создании деятельности?

У меня есть игра с полноэкранным режимом SurfaceView (Portrait) и нитью, которая постоянно отображается на поверхности.

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) Проблема сводится к поиску высоты выреза дисплея.

2 ответа

Кажется, нет никакого способа получить 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
    }
}

WindowInsets.getDisplayCutout() возвращает DisplayCutout объект, если присутствует.

Чтобы получить ограничивающий прямоугольник выреза дисплея, вы можете использовать

DisplayCutout.getBoundingRects()

Это даст вам список Rect всех вырезов дисплея (нефункциональная область) на экране.

Чтобы получить высоту каждого выреза дисплея,

Rect.height()

Это может также вернуть отрицательные значения, поэтому убедитесь, что вы взяли модуль высоты.

Для получения дополнительной информации о поддержке вырезов на экране см. Следующие ссылки:

андроид: windowLayoutInDisplayCutoutMode

DisplayCutout

layoutInDisplayCutoutMode

WindowInsets

WindowInsets.getDisplayCutout ()

Эта модификация ответа Романа (выше) сработала для меня:

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

Вот как это сделать в 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()), если вы находитесь в портретном режиме, который задается в исходном вопросе. Этот образец работает для ландшафта.

Прекратите читать частные ресурсы Android и перестаньте вызывать getRealSize(). Просто вызовите getSize(), и значения, которые вы получите, будут полезны.

Другие вопросы по тегам