onApplyWindowInsets вызывается со странной верхней вставкой
У меня есть приложение для Android, которое имеет следующие настройки в своей теме:
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
Вид сверху в иерархии переопределяет onApplyWindowsInsets()
, Реализация просто записывает WindowInsets
он был передан, затем вызывает метод суперкласса, регистрирует результат и возвращает его - ничего не изменяется. Журнал также показывает, что метод суперкласса не изменяет вставки.
Теперь я получаю странно выглядящий верхний вкладыш, который всегда кажется на 56–72 дп больше, чем я ожидал:
Platform DPI Layout Inset Bar Difference
Android x86_64 8.1 MDPI Landscape 88 px/dp 24 px/dp 64 px/dp
Landscape, split 80 px/dp 24 px/dp 56 px/dp
Anbox MDPI Window 64 px/dp None 64 px/dp
LineageOS 15.1 XXHDPI Portrait 240 px/80 dp 72 px/24 dp 168 px/56 dp
Portrait, split/top 216 px/73 dp 72 px/24 dp 144 px/48 dp
Portrait, split/bottom 144 px/48 dp None 144 px/48 dp
SDK Emulator (6.0) HDPI Portrait 120 px/80 dp 36 px/24 dp 84 px/56 dp
Примечание: в альбомном режиме два последовательных вызова onApplyWindowInsets()
, только последние сообщены здесь.
На самом деле представление не расширяется за пределы видимой области: если я рисую область размером 24 пикселя в верхней части моего представления, она отображается в верхней части видимой области (т. Е. Под строкой состояния, если она есть), никогда не за кадром.
Если бы я доверял этим значениям врезки и смещению содержимого на количество пикселей, указанное для того, чтобы оно не касалось системных панелей, я бы закончил с пропуском в верхней части представления.
Насколько я могу судить, значения влево / вправо / вниз кажутся нормальными.
Как я могу это исправить? Я что-то пропускаю?
1 ответ
Поскольку у меня до сих пор нет объяснения представленных значений, я предполагаю, что это либо ошибка, либо плохо документированная функция, которая, тем не менее, присутствует во многих (если не во всех) версиях Android.
К счастью, по крайней мере в API 23+ есть еще один способ получить вставки окна, а именно: View#getWindow().getRootView().getRootWindowInsets()
, Кажется, в этом есть свои ошибки, а именно сообщение о неправильных вставках для панели навигации, но объединение двух результатов сработало для меня.
- Храните вставки, переданные
onApplyWindowsInsets()
, отбрасывая только верхний. - Override
onSizeChanged()
для просмотра, и в нем зовутView#getRootWindowInsets()
чтобы получить верхнюю вставку (игнорировать другие).
Объединенные ценности работали для меня.
К сожалению, это не будет работать на API 20–22, который не реализует View#getRootWindowInsets()
, Здесь вам нужно будет сделать некоторые догадки. К счастью, это проще, поскольку эти API еще не реализуют разделенный экран - верхняя вставка будет высотой строки состояния, если вы явно не запросили ее скрытие (в этом случае это 0). Если строка состояния видна, ее высоту можно определить следующим образом:
Resources resources = view.getResources();
int shid = resources.getIdentifier("status_bar_height", "dimen", "android");
padding_top = (shid > 0) ? resources.getDimensionPixelSize(shid) : 0;