3

Эта проблема на самом деле возникла в более сложной ситуации, связанной с изменениями ориентации и различными макетами для портретной и ландшафтной архитектуры, но в ее минимальной версии проблема такова:Как восстановить систему из SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION?

Мы хотели бы переключаться между «нормальными» и «нормальными», полноэкранный "макет, т.е. е .:

  • один макет, в котором содержание только занимает место, что осталось внутри панели навигации и панели состояния
  • один макет, где содержание занимает весь экран и слайды в рамках как навигации и панели состояния

для переключения из нормальных в полноэкранном режиме мы используем:

public static final int EXPAND_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STABLE 
       | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 
       | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 

getWindow().getDecorView().setSystemUiVisibility(EXPAND_FLAGS); 

И переключиться обратно мы пытались:

public static final int SHRINK_FLAGS = View.SYSTEM_UI_FLAG_VISIBLE; 

getWindow().getDecorView().setSystemUiVisibility(SHRINK_FLAGS); 

Таким образом, из этого

Layout after app start

мы первый "развернуть" на это:

Layout after "expand" click

но "усадка" назад не работает:

Layout after "expand" and "shrink"

Итак, кажется, что, хотя активности разрешено рисовать внутри пользовательского интерфейса системы, он все еще «думает», что он должен оставить пространство для пользовательского интерфейса системы.

Так что я задаю вопрос: что должно быть SHRINK_FLAGS в моем коде выше или что я должен делать совершенно по-другому?

Мы используем AppCompatActivity с темой Theme.AppCompat.Light.DarkActionBar.

ответ

2

Кажется, что корень вашего макета имеет android:fitsSystemWindows="true". По какой-то причине, о которой я не знаю, fitsSystemWindows не работает при изменении флагов интерфейса системы. К счастью, есть обходной путь для этой проблемы.

Сначала установите расширение флагов системы UI безусловно:

getWindow().getDecorView().setSystemUiVisibility(
     View.SYSTEM_UI_FLAG_LAYOUT_STABLE 
       | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 
       | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 
); 

Затем удалите android:fitsSystemWindows="true" из всех представлений предков макета.

После этого создайте макет, который будет обрабатывать изменения в системных вставках и добавлять или удалять дополнения в зависимости от значения его свойства. Это самая сложная часть. Вы должны обрабатывать системные вставки по-разному в зависимости от версии платформы.Для версий ниже 20 (KitKat Watch), вы должны переопределить View.fitSystemWindows() метод:

@Override 
protected boolean fitSystemWindows(final Rect insets) { 
    if (mFit) { 
     setPadding(insets.left, insets.top, insets.right, insets.bottom); 
     // Do not propagate the system insets further. 
     return true; 
    } else { 
     setPadding(0, 0, 0, 0); 
     // Do not consume the insets and allow other views handle them. 
     return false; 
    } 
} 

Для версии платформы большей или равной чем 20 вам нужно переопределить View.onApplyWindowInsets() метод и к такой же обработке, как и в предыдущем методе:

@Override 
public WindowInsets onApplyWindowInsets(final WindowInsets insets) { 
    if (mFit) { 
     setPadding(
       insets.getSystemWindowInsetLeft(), 
       insets.getSystemWindowInsetTop(), 
       insets.getSystemWindowInsetRight(), 
       insets.getSystemWindowInsetBottom() 
     ); 
     return insets.consumeSystemWindowInsets(); 
    } else { 
     setPadding(0, 0, 0, 0); 
     return insets; 
    } 
} 

И, наконец, создать сеттер для mFit поля, которое уведомит систему, что она должна применяться врезками снова:

mFit = fit; 
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { 
    requestApplyInsets(); 
} else { 
    requestFitSystemWindows(); 
} 

Теперь вы можете позвонить setFit(false), чтобы сделать свой макет позади пользовательского интерфейса системы и setFit(true), чтобы сделать макет подходящим системным окнам.

Вы можете получить исходный текст для этого макета here.

+0

Я не понимаю, как это работает, но вы спасли мою задницу, спасибо! –