- Transparent Android system navigation bar with Flutter and FlexColorScheme
- Sysnavbar with FlexColorScheme
- About this Example
- Android setup
- Support both transparent and color branded sysnavbar
- WindowInsets — listeners to layouts
- Moving where we handle insets to where our views live, layout files
- Drawing behind the navigation bar
- Handling insets through padding
- doOnApplyWindowInsets
- requestApplyInsetsWhenAttached()
- Wrapping it up in a bind
- Android Data Binding: Custom Setters
- Make Data Binding Do What You Want
- android:fitSystemWindows
- Why would I want to fitsSystemWindows?
- Ergonomics FTW
- Как навсегда скрыть панель навигации в активности Android?
- Как скрыть строку состояния и панель навигации | Android-студия
Transparent Android system navigation bar with Flutter and FlexColorScheme
Sysnavbar with FlexColorScheme
Transparent Android system navigation bar with Flutter and FlexColorScheme.
About this Example
This an extra Android companion example to the Flutter
package FlexColorScheme.
It is a slight modification of example nr 5 bundled with the package and shows
how FlexColorScheme can be used to make a transparent system navigation bar in
Flutter Android applications.
Android setup
To make transparent system navigation bar in Flutter you must also make this change to them MainActivity.kt
file in your Flutter Android embedder:
in ../android/app/src/main the default MainActivity.kt for your project:
Additionally, you must use Android SDK 30 to build the Flutter Android project, so you also need to update
your build.gradle file in ../android/app from:
You can find additional info and discussion about transparent system navigation in Flutter Android apps in
Flutter issue 69999, it was that discussion that lead me
to adding this experimental support for it in FlexColorScheme.
Support both transparent and color branded sysnavbar
When you want to use color branded system navigation bar it is best to never put any transparency on it if it is not
supported. Adding transparency to the system navigation bar color when it is not supported, will just make
the color on it transparent and show the default scrim color used on the system navigation bar. This will not look
very nice.
If you design your app to use transparent system navigation bar when it is supported, and then want to use and have a
nice looking color branded background colored system navigation bar, when transparency is not supported, then we must
check which Android SDK level the application is running on and adjust the behaviour accordingly. We can use the
package device_info to get the Android SDK level and keep the opacity as 1 when SDK level is below 30.
This example presents one suggestion on how this can be implemented, and the different approach to the design for
the use cases.
In the sub-page in this example, it also shows how you can use a fully transparent system navigation bar when possible,
and for the case when this is not possible, a color branded opaque one. Then combine this with a same background primary
color branded Material BottomNavigationBar using a slight transparency. For the case that support
transparency on the system navigation bar, when it is placed on top of this BottomNavigationBar with its slight
transparency, it makes BottomNavigationBar and system navigation bar look like one shared translucent bottom area,
with content scrolling behind it.
For the case when the system navigation bar transparency is not supported, it still has
the same color as the BottomNavigationBar , but without the transparency, so it does not clash so badly
with it. The BottomNavigationBar still keeps it slight transparency, and we can at least see content scrolling behind
it.
Instead of just transparency on the bottom navigation bar, you can add a container to it with blur filter in it,
you can then recreate the iOS frosted glass blur effect and have that on the system navigation bar too.
This is not shown in this demo, but is e.g. used by one of the configuration options offered for Material
BottomNavigationBar in Flexfold.
The end result is an app looking like the left one, when transparency is supported and like the right one,
when it is not. I kind of like it.
Источник
WindowInsets — listeners to layouts
Moving where we handle insets to where our views live, layout files
If you’ve watched my Becoming a Master Window Fitter talk, you’ll know that handling window insets can be complex. Recently I’ve been improving system bar handling in a few apps, enabling them to draw behind the status and navigation bars. I’ve come up with some methods which make handling insets easier.
Drawing behind the navigation bar
For the rest of this post we will be going through a simple example using a BottomNavigationView , which is laid out at the bottom of the screen. It is very simply implemented as so:
By default, your Activity’s content will be laid out within the system provided UI (navigation bar, etc), thus our view sits flush to the navigation bar. Our designer has decided that they would like the app to start drawing behind the navigation bar though. To do that we’ll call setSystemUiVisibility() with the appropriate flags:
And finally we will update our theme so that we have a translucent navigation bar, with dark icons:
As you can see, this is only the beginning of what we need to do though. Since the Activity is now laid out behind the navigation bar, our BottomNavigationView is too. This means the user can’t actually click on any of the navigation items. To fix that, we need to handle any WindowInsets which the system dispatches, and use those values to apply appropriate padding to views.
Handling insets through padding
One of the usual ways to handle WindowInsets is to add padding to views, so that their contents are not displayed behind the system views. To do that, we can set an OnApplyWindowInsetsListener to add the necessary bottom padding to the view, ensuring that its content isn’t obscured.
OK great, we’ve now correctly handled the bottom system window inset. But later the designer decided to add some padding in the layout too:
Note: I’m not recommending using 24dp of vertical padding on a BottomNavigationView, I am using a large value here just to make the effect obvious.
Hmmm, that’s not right. Can you see the problem? Our call to updatePadding() from the OnApplyWindowInsetsListener will now wipe out the intended bottom padding from the layout.
Aha! Lets just add the current padding and the inset together:
We now have a new problem. WindowInsets can be dispatched at any time, and multiple times during the lifecycle of a view. This means that our new logic will work great the first time, but for every dispatch we’re going to be adding more and more bottom padding. Not what we want. 🤦
The solution I’ve come up with is to keep a record of the view’s padding values after inflation, and then refer to those values instead. Example:
This works great, and means that we maintain the intention of the padding from the layout, and we still inset the views as required. Keeping object level properties for each padding value is very messy though, we can do better… 🤔
doOnApplyWindowInsets
Enter my new doOnApplyWindowInsets() extension method. This is a wrapper around setOnApplyWindowInsetsListener() which generalises the pattern above:
When we need a view to handle insets, we can now do the following:
requestApplyInsetsWhenAttached()
You may have noticed the requestApplyInsetsWhenAttached() above. This isn’t strictly necessary, but does work around a limitation in how WindowInsets are dispatched. If a view calls requestApplyInsets() while it is not attached to the view hierarchy, the call is dropped on the floor and ignored.
This is a common scenario when you create views in Fragment.onCreateView() . The fix would be to make sure to simply call the method in onStart() instead, or use a listener to request insets once attached. The following extension function handles both cases:
Wrapping it up in a bind
At this point we’ve greatly simplified how to handle window insets. We are actually using this functionality in some upcoming apps, including one for an upcoming conference 😉. It still has some downsides though:
- The logic lives away from our layouts, meaning that it is very easy to forget about.
- We will likely need to use this in a number of places, leading to lots of near-identical copies spreading throughout the app.
I knew we could do better.
So far this entire post has concentrated solely on code, and handling insets through setting listeners. We’re talking about views here though, so in an ideal world we would declare our intention to handle insets in our layout files.
Enter data binding adapters! If you’ve never used them before, they let us map code to layout attributes (when you use Data Binding). You can read more about them here:
Android Data Binding: Custom Setters
Make Data Binding Do What You Want
So lets create an attribute to do this for us:
In our layout we can then simply use our new paddingBottomSystemWindowInsets attribute, which will automatically update with any insets.
Hopefully you can see how ergonomic and easy to use this is compared to using an OnApplyWindowListener alone. 🌠
But wait, that binding adapter is hardcoded to only set the bottom dimension. What if we need to handle the top inset too? Or the left? Or right? Luckily binding adapters let us generalise the pattern across all dimensions really nicely:
Here we’ve declared an adapter with multiple attributes, each mapping to the relevant method parameter. One thing to note, is the usage of requireAll = false , meaning that the adapter can handle any combination of the attributes being set. This means that we can do the following for example, setting both the left and bottom:
Ease of use level: 💯
android:fitSystemWindows
You might have read this post, and thought “ Why hasn’t he mentioned the fitSystemWindows attribute?”. The reason for that is because the functionality that the attribute brings is not usually what we want.
If you’re using AppBarLayout, CoordinatorLayout, DrawerLayout and friends, then yes use it. Those views have been built to recognize the attribute, and apply window insets in an opinionated way relevant to those views.
The default View implementation of android:fitSystemWindows means to pad every dimension using the insets though, and wouldn’t work for the example above. For more information, see this blog post which is still very relevant:
Why would I want to fitsSystemWindows?
Ergonomics FTW
Phew, this was a long post! Aside from us making WindowInsets easier to handle, hopefully it has demonstrated how features like extension functions, lambdas, and binding adapters can make any API easier to use.
Источник
Как навсегда скрыть панель навигации в активности Android?
Как скрыть строку состояния и панель навигации | Android-студия
Я хочу постоянно скрывать панель навигации в своей деятельности (а не в пользовательском интерфейсе всей системы). теперь я использую этот кусок кода
Он скрывает панель, но когда пользователь касается экрана, она снова отображается. есть ли способ скрыть это навсегда до активности onStop() ;
- 1 возможный дубликат постоянно скрывать панель навигации при активности
- Здесь, по этой официальной ссылке Google / Android, изложено много хороших и конкретных деталей: Включить полноэкранный режим.
- Флаг автоматически сбрасывается, когда пользователь касается экрана в соответствии с документацией. Вы должны внести изменения в свой дизайн пользовательского интерфейса, чтобы все время скрывать панель навигации.
Фрагменты:
Это для Android 4.4+
Попробуйте иммерсивный режим https://developer.android.com/training/system-ui/immersive.html
Быстрый фрагмент (для Деятельность класс):
Если при нажатии кнопки увеличения или уменьшения громкости возникают проблемы, отображается панель навигации. Я добавил код в onCreate см. setOnSystemUiVisibilityChangeListener
Вот еще один связанный с этим вопрос:
Навигация в режиме погружения становится липкой после нажатия кнопки громкости или минимизации-восстановления
- 4 Когда пользователь проводит пальцем вверх / вниз по экрану, полупрозрачные панели навигации временно появляются, а затем снова скрываются. МОЖНО ЛИ ЭТО СКРЫТЬ?
- @KarthickRamu Я нашел способ, просто посмотрите на мой ответ 🙂
- 1 @MuhammedRefaat Для вашей подсказки требуется устройство с root-доступом 🙁
- 1 @DawidDrozd Спасибо, но у меня проблема. Корневой макет моей активности — RelativeLayout, и у него есть дочернее представление, для которого установлено android: layout_alignParentBottom = «true», панель навигации исчезает, но дочернее представление не перемещается вниз край экрана, как будто панель навигации установлена на невидимку, не исчезла, не могли бы вы помочь?
- 1 Если вы хотите использовать пространство, занимаемое панелью навигации, необходимо удалить все вхождения android:fitsSystemWindows=’true’ с ваших взглядов. Android Studio включает этот атрибут при создании некоторых макетов. См. Stackoverflow.com/a/42501330/650894
Это работает на 100%, и вы можете сделать то же самое для более низких версий API, даже если это запоздалый ответ, я надеюсь, что это поможет кому-то другому.
Если вы хотите, чтобы это было навсегда, просто позвоните FullscreenCall() внутри твоего onResume() метод.
- 2 Я рекомендую взглянуть на developer.android.com/training/system-ui/immersive.html, где объясняется, что ваш метод просто скрывает панель до тех пор, пока не произойдет взаимодействие, и снова вскоре после завершения взаимодействия.
- Большое вам спасибо — вот и все! : D: +1
Для людей, ищущих более простое решение, я думаю, вы можете просто добавить эту строку кода в onStart()
Это называется иммерсивным режимом. Вы можете посмотреть официальную документацию, чтобы узнать о других возможностях.
Согласно сайту разработчика Android
Я думаю, вы не можете (насколько я знаю) скрыть панель навигации навсегда.
Однако вы можете сделать одну уловку. Заметьте, это уловка.
Просто когда navigation bar появляется, когда пользователь касается экрана. Немедленно снова спрячьте это. Это весело.
Проверь это.
См. Это для получения дополнительной информации об этом ..
Скрыть системную панель в планшетах
В планшетах под управлением Android 4+ скрыть панель системы / навигации невозможно.
SYSTEM_UI_FLAG_HIDE_NAVIGATION — это новый флаг, который запрашивает полное скрытие панели навигации. Имейте в виду, что это работает только для панели навигации, используемой некоторыми телефонами (она не скрывает системную панель на планшетах).
Это мое решение:
Сначала определите логическое значение, которое указывает, отображается ли панель навигации или нет.
Второй метод создания, скрывающий панель навигации.
По умолчанию, если вы щелкнете действие после скрытия панели навигации, панель навигации будет видна. Итак, у нас есть состояние, если оно видно, мы его скроем.
Теперь установите OnClickListener на свое представление. Я использую Surfaceview, поэтому для меня:
Также мы должны вызывать этот метод при запуске активности. Потому что мы хотим скрыть это вначале.
Это проблема безопасности: https://stackoverflow.com/a/12605313/1303691
поэтому невозможно навсегда скрыть навигацию на планшете одним единственным вызовом в начале создания представления. Он будет скрыт, но всплывет при касании экрана. Таким образом, всего лишь второе прикосновение к экрану может вызвать событие onClickEvent в макете. Поэтому вам нужно перехватить этот вызов, но я еще не успел это сделать, я обновлю свой ответ, когда узнаю об этом. Или вы уже ответили?
Я думаю, что код удара поможет вам, и добавьте этот код перед setContentView ()
Добавьте этот код за setContentView () getWindow (). GetDecorView (). SetSystemUiVisibility (View.SYSTEM_UI_FLAG_LOW_PROFILE);
- 1 Поле требует API уровня 21+
- НЕТ, это даст мне тот же результат
Думаю, этот код решит вашу проблему. Скопируйте и вставьте этот код в свой MainActivity.java
Он будет работать на Android-10. Надеюсь, это поможет.
В других ответах в основном используются флаги для setSystemUiVisibility() метод в View . Однако этот API устарел с Android 11. Дополнительные сведения см. В моей статье об изменении видимости пользовательского интерфейса системы. В статье также объясняется, как правильно обрабатывать вырезки или как прислушиваться к изменениям видимости.
Вот фрагменты кода для отображения / скрытия системных панелей с новым API, а также устаревшим для обратной совместимости:
Источник