- WindowInsets и fitsSystemWindows
- android:fitsSystemWindows=»true»
- BottomNavigationView
- Why would I want to fitsSystemWindows?
- Customizing fitsSystemWindows
- Examples of customizing fitsSystemWindows
- Use the system, don’t fight it
- Русские Блоги
- android: использование атрибута fitsSystemWindows
- Краткое описание использования атрибута fitsSystemWindows в Android
- Описание недвижимости
- Сценарий приложения
- Использование атрибута
- 1. Эффект по умолчанию
- 2. Эффект после системного окна прозрачен
- 3. После настройки свойств fitsSystemWindows
- Следовать за
- Что именно делает fitsSystemWindows?
WindowInsets и fitsSystemWindows
Любая активность размещается в специальном контейнере и пользователь видит её вместе с системными элементами — строкой состояния, панелью навигации. Всё вместе это контролируется классом Window. Но иногда требуется изменить стандартное поведение. Самый простой пример — игры в полноэкранном режиме, когда мы хотим скрыть все лишние элементы с экрана. Другой вариант — полноэкранный режим, но системные элементы накладываются поверх игры. Ещё один вариант — динамическое изменение, когда пользователь начинает прокручивать список вверх, то системная строка состояния исчезает, а при прокрутке вниз снова появляется.
Любая активность может получить доступ к окну Window через метод Activity#getWindow().
Аналогично класс Dialog имеет своё окно Dialog#getWindow().
В свою очередь окно содержит всю необходимую информацию о размерах системных элементов и подстраивает все дочерние элементы (вашу активность), чтобы не было нигде зазоров или наложений друг на друга. Реализуется взаимное расположение при помощи специальных отступов Inset.
Поведение Window в разных версиях Android менялась. До KitKat была упрощённая версия не учитывала системные элементы управления. Доступ к ним осуществлялся через метод setSystemUiVisibility(). Также было множество флагов настроек: SYSTEM_UI_FLAG_VISIBLE, SYSTEM_UI_FLAG_FULLSCREEN и другие.
Начиная с KitKat, Android стала поддерживать полупрозрачные системные панели. Появились атрибуты androd:windowTranslucentStatus, android:windowsTranslucentNavigation.
В Lollipop происходит дальнейшая интеграция, системные элементы входят в состав Window и появилась возможность управлять фоном через android:windowDrawsSystemBarBackgrounds.
Мы можем узнать цвета системных элементов.
android:fitsSystemWindows=»true»
Данный флаг использовался для этой же цели. Сейчас в документации указано, что флаг считается устаревшим с версии API 20.
Данный флаг не будет иметь значения для многих видов макетов типа LinearLayout, FrameLayout. Но есть несколько видов макетов, к которым флаг применить можно. К таким макетам относятся DrawerLayout, CoordinatorLayout, AppBarLayout, CollapsingToolbarLayout, NavigationView.
Лучше вызывать метод onApplyWindowInsets().
Что делать не надо — вручную прописывать размеры строки состояния в ресурсах. Каждое устройство и каждая версия могут иметь свои размеры системных компонентов и ваша попытка видоизменить размеры приведёт к некрасивым последствиям в виде наслоений разных частей компонентов.
Для решения проблемы используйте методы getSystemWindowInsetLeft(), getSystemWindowInsetTop(), getSystemWindowInsetRight(), getSystemWindowInsetBottom() класса WindowInsets/WindowInsetsCompat.
При разработке собственного компонента можете использовать код:
Как уже упоминалось выше, отступы не работают с некоторыми видами макетов. Вы можете переопределить поведение макета, наследуясь от основного макета и переопределяя метод.
BottomNavigationView
Как работать с нижней частью экрана рассказано в статье WindowInsets — Listeners to layouts (12 Apr 2019).
Источник
Why would I want to fitsSystemWindows?
System windows are the parts of the screen where the system is drawing either non-interactive (in the case of the status bar) or interactive (in the case of the navigation bar) content.
Most of the time, your app won’t need to draw under the status bar or the navigation bar, but if you do: you need to make sure interactive elements (like buttons) aren’t hidden underneath them. That’s what the default behavior of the android:fitsSystemWindows =»true» attribute gives you: it sets the padding of the View to ensure the contents don’t overlay the system windows.
A few things to keep in mind:
- fitsSystemWindows is applied depth first — ordering matters: it’s the first View that consumes the insets that makes a difference
- Insets are always relative to the full window — insets may be applied even before layout happens, so don’t assume the default behavior knows anything about the position of a View when applying its padding
- Any other padding you’ve set is overwritten — you’ll note that paddingLeft / paddingTop /etc is ineffective if you are using android:fitsSystemWindows=»true» on the same View
And, in many cases, such as a full screen video playback, that’s enough. You’d have your full bleed view with no attribute and another full screen ViewGroup with android:fitsSystemWindows=»true» for your controls that you want inset.
Or maybe you want your RecyclerView to scroll underneath a transparent navigation bar — by using android:fitsSystemWindows=»true» in conjunction with android:clipToPadding=»false» , your scrolling content will be behind the controls but, when scrolled to the bottom, the last item will still be padded to be above the navigation bar (rather than hidden underneath!).
Customizing fitsSystemWindows
But this default behavior is just that: a default. On KitKat and below, your custom View could override fitSystemWindows() and provide any functionality you wanted — just return true if you’ve consumed the insets or false if you’d like to give other Views a chance.
However, on Lollipop and higher devices, we provide some new APIs to make customizing this behavior much easier and consistent with other behaviors for Views. You’ll instead override onApplyWindowInsets() , which allows the View to consume as much or as little of the insets as you need and be able to call dispatchApplyWindowInsets() on child views as needed.
Even better, you don’t even need to subclass your Views if you only need custom behavior on Lollipop and higher — you can use ViewCompat.setOnApplyWindowInsetsListener() , which will be given preference over the View’s onApplyWindowInsets() . ViewCompat also provides helper methods for calling onApplyWindowInsets( ) and dispatchApplyWindowInsets() without version checking.
Examples of customizing fitsSystemWindows
While the basic layouts ( FrameLayout , LinearLayout , etc) use the default behavior, there are a number of layouts that already customize how they react to fitsSystemWindows to fit specific use cases.
One example is the navigation drawer which needs to span the whole screen and appear under a transparent status bar.
Here, DrawerLayout uses fitsSystemWindows as a sign that it needs to inset its children (such as the main content view — just like the default behavior), but still draw the status bar background (which defaults to your theme’s colorPrimaryDark ) in that space as per the material design specs.
You’ll note DrawerLayout calls dispatchApplyWindowInsets() for each child on Lollipop and higher to allow child views to also receive fitsSystemWindows , a departure from the default (where normally it would simply consume the insets and children would never receive fitsSystemWindows ).
CoordinatorLayout also takes advantage of overriding how it handles window insets, allowing the Behavior set on child Views to intercept and change how Views react to window insets, before calling dispatchApplyWindowInsets() on each child themselves. It also uses the fitsSystemWindows flag to know if it needs to paint the status bar background.
Similarly, CollapsingToolbarLayout looks for fitsSystemWindows to determine when and where to draw the content scrim — a full-bleed scrim which overlays the status bar area when the CollapsingToolbarLayout is scrolled sufficiently off the screen.
If you’re interested in seeing some of the common cases that accompany the Design Library, check out the cheesesquare sample app.
Use the system, don’t fight it
One thing to keep in mind is that it isn’t called fitsStatusBar or fitsNavigationBar . What constitutes system windows, their dimensions, and location may certainly change with different platform releases — for a perfect example, look at the differences between Honeycomb and Ice Cream Sandwich.
Just rest assured that the insets you do get from fitsSystemWindows will be correct on all platform versions to ensure your content does not overlap with system provided UI components — make sure to avoid any assumptions on their availability or size if you customize the behavior.
Источник
Русские Блоги
android: использование атрибута fitsSystemWindows
Краткое описание использования атрибута fitsSystemWindows в Android
Атрибут fitsSystemWindows — это пункт знаний, который я задействовал в изучении иммерсивного режима, поскольку он связан с различием между различными версиями Android, поэтому он также был в облаке в то время, поэтому я специально организовал этот атрибут сегодня.
Описание недвижимости
Атрибут fitsSystemWindows позволяет представлению настраивать свою компоновку в соответствии с системным окном, иными словами, учитывается ли компоновка системного окна при настройке компоновки приложения, здесь системное окно включает в себя строку состояния системы, панель навигации, метод ввода и т. Д., Включая некоторые полосы системы мобильного телефона. Внизу есть виртуальные кнопки.
android: fitsSystemWindows = ”true” (вызвать атрибут отступа View, чтобы освободить место для системного окна)
Это свойство может быть установлено для любого представления, если это свойство установлено, все другие свойства заполнения этого представления недопустимы, и действующее условие этого свойства — только когда прозрачная строка состояния (StatusBar) или Это свойство вступит в силу только в NavigationBar.
Примечание: fitsSystemWindows работает только на системах Android 4.4 и выше, поскольку система StatusBar ниже 4.4 не имеет прозрачного статуса.
Сценарий приложения
Под разные версии Android, адаптация строки состояния приложения и строки состояния самой системы в разных версиях;
Совместимо с системами мобильных телефонов с виртуальными кнопками внизу.
Использование атрибута
1. Эффект по умолчанию
Сначала опубликуйте изображение макета теста, когда строка состояния системы и панель навигации не установлены прозрачно:
2. Эффект после системного окна прозрачен
Когда прозрачная строка состояния (StatusBar) и прозрачная панель навигации (NavigationBar) установлены, изображение эффекта:
Настройки прозрачного состояния штрих-кода:
Настройка кода прозрачной панели навигации:
Если есть один из двух вышеупомянутых случаев, наша строка состояния (StatusBar) или панель навигации (NavigationBar) станут прозрачными, а раскладка развернется до положения StatusBar или NavigationBar.
Примечание. Возникает вопрос о прозрачном стиле строки состояния и панели навигации. Это определяется версией Android. Эффект прозрачности ниже 4.4 отсутствует, полностью прозрачный 4.4
5.0, а прозрачный 5.0 и выше. Для тестирования я использовал симулятор версии 5.0 или выше, поэтому он прозрачный.
3. После настройки свойств fitsSystemWindows
Теперь пришло время появления нашего ключевого атрибута fitsSystemWindows. Просто добавьте android: fitsSystemWindows = «true» в корневой макет, как показано ниже:
После установки атрибута android: fitsSystemWindows = ”true” прозрачная верхняя панель автоматически добавит paddingTop со значением, равным высоте строки состояния, а прозрачная системная панель навигации автоматически добавит paddingBottom со значением, равным высоте панели навигации.
Вставьте код макета:
Следовать за
Прикрепите код Java, чтобы получить строку состояния StatusBar и высоту панели навигации NavigationBar:
Источник
Что именно делает fitsSystemWindows?
Я пытаюсь понять концепцию fitsSystemWindows поскольку в зависимости от вида он делает разные вещи. Согласно официальной документации, это
Логический внутренний атрибут для настройки макета представления на основе системных окон, таких как строка состояния. Если true, настраивает прописку этого вида, чтобы оставить пространство для системных окон .
Теперь, проверяя класс View.java я вижу, что при установке значения true вставки окна (строка состояния, панель навигации …) применяются к окнам просмотра, которые работают в соответствии с приведенной выше документацией. Это важная часть кода:
С новым дизайном материала появляются новые классы, которые широко используют этот флаг, и именно здесь возникает путаница. Во многих источниках fitsSystemWindows упоминается как флаг, чтобы установить, чтобы заложить представление позади системных баров. См. Здесь .
Документация в ViewCompat.java для setFitsSystemWindows гласит:
Устанавливает, должно ли это представление учитывать учетные данные системного экрана, такие как строка состояния и вставка его содержимого; То есть, будет ли выполняться реализация по умолчанию <@link View # fitSystemWindows (Rect)>. См. Этот метод для более подробной информации .
В соответствии с этим, fitsSystemWindows просто означает, что функция fitsSystemWindows() будет выполнена? Новые классы материалов, похоже, просто используют это для рисования в строке состояния. Если мы посмотрим на DrawerLayout.java , мы увидим это:
И мы видим тот же шаблон в новом CoordinatorLayout или AppBarLayout .
Разве это не работает точно так же, как документация для fitsSystemWindows ? В последних случаях это означает, что нужно заглянуть за панели системы .
Однако, если вы хотите, чтобы FrameLayout рисовал себя за строкой состояния, установка fitsSystemWindows в true не делает этого трюка, поскольку реализация по умолчанию делает то, что документировано изначально. Вы должны переопределить его и добавить те же флаги, что и другие упомянутые классы. Я что-то упускаю?
Он не затягивается за системный план, он как бы растягивается за панелью, чтобы подкрасить его теми же цветами, что и у него, но просмотренные в нем представления заполняются в строке состояния, если это имеет смысл
Системные окна – это части экрана, на которых система рисует либо неинтерактивную (в случае строки состояния), либо интерактивную (в случае панели навигации).
В большинстве случаев ваше приложение не нужно будет рисовать под панелью состояния или панель навигации, но если вы это сделаете: вам нужно убедиться, что интерактивные элементы (например, кнопки) не скрыты под ними. Именно это дает поведение по умолчанию для атрибута android: fitsSystemWindows = «true»: оно устанавливает заполнение представления, чтобы содержимое не перекрывало системные окна.
Источник