Как контролировать приоритет наложения WindowManager в Oreo?

У меня есть наложение для моего приложения, OV1, которое представляет собой кнопку, которую пользователь может перемещать на своем экране. Когда этот оверлей нажимается, он порождает второй оверлей, OV2, который содержит несколько вспомогательных кнопок, расположенных вокруг текущего местоположения OV1. OV2 также затемняет остальную часть экрана, пока присутствует, используя флаг WindowManager.LayoutParams.FLAG_DIM_BEHIND.

Одна проблема, с которой я столкнулся при первоначальной реализации вышеизложенного, заключается в том, что эффект затемнения накладывался на все, что не является OV2, включая OV1, затемнение и отключение, что не позволяет закрывать OV2, поскольку OV1 является кнопкой переключения. Решением, которое я нашел, было задание параметров макета по-разному для каждого наложения:

OV1 получает:

params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;

Принимая во внимание, что OV2 получает:

params.type = WindowManager.LayoutParams.TYPE_PHONE

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

Это всегда работало нормально, пока я не начал обновлять приложение для Android API 27 (Oreo). Как часть необходимых изменений, мне пришлось изменить оба типа параметров оверлеев на WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, поэтому я утратил способность отдавать OV1 более высокий приоритет, чтобы он оставался поверх OV2. Есть ли альтернативный способ воспроизвести это поведение, гарантируя, что OV1 остается самым верхним наложением, или вытесняя его на передний план всякий раз, когда OV2 порождается?

1 ответ

Решение

Хотя я никогда не находил решения для этого, один из обходных путей состоит в том, чтобы заново прикрепить оверлеи к оконному менеджеру в заданном порядке (когда в оконный менеджер добавлено несколько представлений типа TYPE_APPLICATION_OVERLAY, самые последние из них идут сверху), вызвав removeViewImmediate() с последующим addView() для представления, которое вы хотите быть сверху.

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

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