Как исправить: значки на панели навигации все еще отображаются при открытии всплывающего меню (Полноэкранный режим — залипание с эффектом погружения)

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

Предпочтительно, я бы хотел, чтобы они были полностью удалены, но, судя по тому, что я читал, это невозможно, если вы не рутируете устройство.

Итак, мой вопрос в основном таков: Как мне скрыть значки панели навигации, когда я показываю всплывающее меню?

ДО

ДО

ПОСЛЕ

ПОСЛЕ

До сих пор я пробовал:

  • Вызов hideNavigation() до и после отображения всплывающего меню
  • Звонок hideNavigation() в onCreate(), onResume() & onWindowFocusChanged()
  • Запрос фокуса на другое представление
  • Попытка очистить фокус из раскрывающегося списка (неудачная попытка, на самом деле не нашел способ сделать это)
  • Изменение цвета значка, «подделка» его будет скрыто (неудачная попытка, на самом деле не нашел способ сделать это)
  • Использование hideNavigation() в сочетании с Handler (Неудачная попытка, возможно я не правильно сделал)
  • Пытаюсь настроить некоторые параметры режима COSU/KIOSK (Возможно, есть какой-то способ полностью отключить всю панель навигации? Я пока не нашел способа скрыть кнопку возврата)

МЕРОПРИЯТИЯ


    class PinCodeActivity, HasTitleBar {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_pin_code)
            initTitleBarWith(this)
            hideNavigation()
        }

        override fun onResume() {
            super.onResume()
            hideNavigation()
        }

        fun hideNavigation() {
            window.decorView.apply {
                systemUiVisibility = FLAGS
            }
        }

        override fun onWindowFocusChanged(hasFocus: Boolean) {
            super.onWindowFocusChanged(hasFocus)
            hideNavigation()
        }
    }

const val FLAGS = (View.SYSTEM_UI_FLAG_LOW_PROFILE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)

ЗАГОЛОВКА


    fun HasTitleBar.initTitleBarWith(activity: Activity, resId: Int = R.id.titleBar) {
        val langButton = activity.findViewById<View>(resId).findViewById<Button>(R.id.tbLanguageChoiceBtn)
        val wrapper = ContextThemeWrapper(activity, R.style.MyPopupMenu)
        val popupMenu = PopUpLanguageMenu(wrapper, langButton)
        langButton.setOnClickListener {
            activity.hideNavigation()
            popupMenu.showMenu()
            activity.hideNavigation()
        }
    }

ВСПЛЫВАЮЩЕЕ МЕНЮ


    class PopUpLanguageMenu constructor(context: Context, view: View) : PopupMenu(context, view) {

        private var popupHelper: MenuPopupHelper

        init {
            val popUpMenu = PopupMenu(context, view).apply {
                inflate(R.menu.menu_language_dropdown)
            }

            popupHelper = MenuPopupHelper(context, popUpMenu.menu as MenuBuilder, view)
            popupHelper.run {
                gravity = Gravity.END
                setForceShowIcon(true)
            }
        }

        fun showMenu() {
            popupHelper.show()
        }
    }

ОЖИДАЕМЫЙ РЕЗУЛЬТАТ: панель навигации и ее значки скрыты, после отображения всплывающего меню значки по-прежнему СКРЫТЫ

ФАКТИЧЕСКИЙ РЕЗУЛЬТАТ: панель навигации и ее значки скрыты, после отображения всплывающего меню значки ПОКАЗАНЫ


person Tobias Heuts    schedule 11.01.2019    source источник


Ответы (1)


Навигационная панель снова появляется, потому что в верхней части стека представлений отображается новый элемент DecorView (PopupDecorView), на который не влияют ранее установленные вами флаги.

Здесь нет серебряной пули, мой подход состоит в том, чтобы копаться в WindowManagerGlobal путем отражения и вылавливать представление просмотра, снова применять к нему системные ФЛАГИ, поэтому после появления PopupMenu ему удается скрыть панель навигации сразу после этого ( есть еще одно отображение из панели навигации).

Вот код:

override fun onWindowFocusChanged(hasFocus: Boolean) {
    super.onWindowFocusChanged(hasFocus)
    if (hasFocus) {
        hideNavigation()
    } else {
        // When PopupMenu appears, the current Activity looses the focus
        setFlagsOnThePeekView() // Hijack to the current peek view, apply the Flags on it
    }
}

@SuppressLint("PrivateApi")
fun setFlagsOnThePeekView() {
    try {
        val wmgClass = Class.forName("android.view.WindowManagerGlobal")
        val wmgInstance = wmgClass.getMethod("getInstance").invoke(null)
        val viewsField = wmgClass.getDeclaredField("mViews")
        viewsField.isAccessible = true

        val views = viewsField.get(wmgInstance) as ArrayList<View>
        // When the popup appears, its decorView is the peek of the stack aka last item
        views.last().apply { 
            systemUiVisibility = FLAGS
            setOnSystemUiVisibilityChangeListener {
                systemUiVisibility = FLAGS
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}
person Trung Le    schedule 11.01.2019
comment
Прекрасно работает! Это единственное решение, которое работает без сбоев. - person Lucas De Morais Cabrales; 01.08.2019
comment
рад, что помогает :-) - person Trung Le; 01.08.2019
comment
Определенно следует избегать использования защищенных классов, поскольку они могут не работать на некоторых устройствах в производственной среде. - person Sarthak Mishra; 27.01.2021
comment
@SarthakMishra, как я уже упоминал, здесь пока нет серебряной пули, если вы знаете одно, мы все слушаем. Ваша озабоченность верна, но ее также нужно поставить в правильный контекст. Запускаете ли вы приложение KIOS публично, не зная места назначения установки устройства/ОС? :D - person Trung Le; 28.01.2021
comment
Я понимаю, чувак, что это взлом. Было бы лучше, если бы вы могли упомянуть о последствиях использования решения в рабочем приложении. Это помогло бы тем, кто не настолько продвинут в разработке Android, понять, на что они подписываются :) - person Sarthak Mishra; 28.01.2021