Обнаружение, когда системные кнопки видны при использовании режима "immersive"

В настоящее время я использую режим immersive (API 19) для одной из моих операций следующим образом:

getWindow().getDecorView()
            .setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                            | View.INVISIBLE);

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

Любые идеи?

Ответы

Ответ 1

Из видео разработчика Android Developers, когда вы находитесь в режиме погружения в липкость, приложение не уведомляется.

Иммерсивный липкий режим начинается с 6:56 и около 7:25 Роман Нурик говорит, что слушатель не будет запущен.

Это видео: http://youtu.be/cBi8fjv90E4?t=6m56s

Ответ 2

ОБНОВЛЕННЫЙ ОТВЕТ:

Установите OnSystemUiVisibilityChangeListener, принудительно импортируйте режим, когда видимость равна 0 (вместо 6).

if(android.os.Build.VERSION.SDK_INT >= 19) {
        getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
            @Override
            public void onSystemUiVisibilityChange(int visibility) {
                if(visibility == 0) {
                    getWindow().getDecorView().setSystemUiVisibility(
                            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
                }
            }
        });
    }

OLD, NASTY ANSWER:

Это неприятно, но это решение IFF, в котором вы показываете ActionBar:

  • добавьте OnGlobalLayoutListener в ViewTreeObserver из файла action_bar_container.
  • в реализации OnGlobalLayoutListener, проверьте, отображается ли видимость "action_bar_container", если GONE или нет.
  • когда он переместился с GONE на! GONE (и предположил, что вы находитесь в режиме погружения), затем снова принудительно импортируйте режим с помощью метода setSystemUiVisibility.

if(android.os.Build.VERSION.SDK_INT >= 19) {
        int actionBarContainerId = Resources.getSystem().getIdentifier("action_bar_container", "id", "android");
        ((ViewGroup)findViewById(actionBarContainerId)).getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int actionBarContainerId = Resources.getSystem().getIdentifier("action_bar_container", "id", "android");
                ViewGroup actionBarContainer = (ViewGroup) findViewById(actionBarContainerId);
                if(actionBarContainer.getVisibility() == View.GONE) {
                    if(DEBUG) Log.d(TAG, "...PROBABLY IN IMMERSIVE MODE AND ALL IS GOOD!..");
                } else {
                    if(DEBUG) Log.d(TAG, "...PROBABLY NO LONGER IN IMMERSIVE MODE, HEY..");
                    getWindow().getDecorView().setSystemUiVisibility(
                            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
                }

            }
        });
    }

Ответ 3

Я нашел решение, которое мне подходит, хотя оно и не идеально. Я устанавливаю видимость пользовательского интерфейса View.SYSTEM_UI_FLAG_IMMERSIVE вместо View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY, и когда я получаю обратный вызов onSystemUiVisibilityChange, я задерживаю сообщение обработчику с reset видимостью пользовательского интерфейса. Вот код:

private static final int FULL_SREEN_MSG = 10;
private static final long TIME_BEFORE_HIDE_UI = 2 * DateUtils.SECOND_IN_MILLIS;

private final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        if (msg.what == FULL_SREEN_MSG) {
            setFullscreen();
        }
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setFullscreen();
    getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
}

private void setFullscreen() {
    getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                    | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_IMMERSIVE);
}

@Override
public void onSystemUiVisibilityChange(int visibility) {
    if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
        mHandler.sendEmptyMessageDelayed(FULL_SREEN_MSG, TIME_BEFORE_HIDE_UI);
    }
}

Ответ 4

В 4.4 приложение не получит каких-либо признаков, когда панели временных индикаторов обнаруживаются или автоматически скрыты (под IMMERSIVE_STICKY), либо через OnSystemUiVisibilityChangeListener, либо другими средствами.

Вы можете прислушиваться к ошибкам, похожим на прослушивание жестов системы, но это не является частью публичного api, оно может изменения в будущих выпусках и разные устройства.

Мне любопытно, что вы хотите сделать, когда кратковременные системные бары отображаются/скрыты.