Навигация в иммерсивном режиме становится липкой после громкого нажатия или минимизации-восстановления

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        this.getWindow().getDecorView().setSystemUiVisibility(getSystemUiFlags());
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    private static int getSystemUiFlags() {
            return View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
    }

}

После первого запуска

После первого запуска

После нажатия кнопок громкости или после недавнего нажатия приложений дважды

Я видел, что приложение QuickPic не имеет этой ошибки. Интересно, как они это пропустили.

3 ответа

Решение

У меня работает следующий код:

public void updateUI() {
    final View decorView = getWindow().getDecorView();
    decorView.setOnSystemUiVisibilityChangeListener (new View.OnSystemUiVisibilityChangeListener() {
        @Override
        public void onSystemUiVisibilityChange(int visibility) {
            if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                decorView.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);
                }
            }
        });
}

И позвонил слушателю на onCreate а также onResume методы:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    updateUI();
}

@Override
public void onResume() {
    super.onResume();
    updateUI();
}

Мое решение состоит в том, чтобы установить флаги UI-Visibility в трех местах:

  1. При получении фокуса
  2. В onResume
  3. В слушателе OnSystemUiVisibilityChangeListener

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

  private void setupMainWindowDisplayMode() {
    View decorView = setSystemUiVisilityMode();
    decorView.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
      @Override
      public void onSystemUiVisibilityChange(int visibility) {
        setSystemUiVisilityMode(); // Needed to avoid exiting immersive_sticky when keyboard is displayed
      }
    });
  }

  private View setSystemUiVisilityMode() {
    View decorView = getWindow().getDecorView();
    int options;
    options =
        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_STICKY;

    decorView.setSystemUiVisibility(options);
    return decorView;
  }

setupMainWindowDisplayMode () вызывается в onCreate().

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

Кажется, что при нажатии кнопки громкости "флаги", относящиеся к "режиму погружения", сбрасываются. И я думаю, именно поэтому режим погружения отключен, и режим погружения не восстанавливается автоматически.

Поэтому я попытался установить "флаги" после нажатия кнопки громкости с "запущенным" объектом.

Итак, это работает так:

режим погружения -> кнопка громкости нажата (флажки сняты) -> через 500 мс, работающий объект снова устанавливает флажки -> режим погружения восстановлен

1. Сначала определите объект runnable для установки флагов

private Runnable decor_view_settings = new Runnable()
{
    public void run() 
    {
        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);
    }
};

2. Опубликовать работающий объект с некоторой задержкой в ​​обработчике при нажатии кнопки громкости

private Handler mHandler = new Handler();

...

@Override 
public boolean onKeyDown(int keyCode, KeyEvent event) 
{
    if(keyCode == KeyEvent.KEYCODE_BACK)
    {
        finish();
    }
    else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP)
    {
        mHandler.postDelayed(decor_view_settings, 500);
    }

    return super.onKeyDown(keyCode, event);
}

Я просто отложил это на 500 мс без причины, это не важно.

3. Базовый код для режима погружения с работающим объектом

@Override
public void onWindowFocusChanged(boolean hasFocus) 
{
    super.onWindowFocusChanged(hasFocus);

    if(hasFocus) 
    {
        mHandler.post(decor_view_settings);
    }
}

Это отлично сработало на моем приложении.

Таким образом, когда я нажимаю кнопку громкости, режим погружения отключается, и всплывающее меню громкости появляется.

через несколько секунд качелька громкости исчезнет, ​​как и строка состояния и панель навигации.

Надеюсь, эта работа для вас.

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