Что именно делает fitsSystemWindows?

126

Я изо всех сил пытаюсь понять концепцию, fitsSystemWindowsпоскольку в зависимости от точки зрения он делает разные вещи. Согласно официальной документации это

Логический внутренний атрибут для настройки макета представления на основе системных окон, таких как строка состояния. Если true, регулирует отступ этого представления, чтобы оставить место для системных окон .

Теперь, проверяя View.javaкласс, я вижу, что при установке trueна вставки окна (строка состояния, панель навигации ...) применяются к отступам представления, что работает в соответствии с документацией, приведенной выше. Это соответствующая часть кода:

private boolean fitSystemWindowsInt(Rect insets) {
    if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
        mUserPaddingStart = UNDEFINED_PADDING;
        mUserPaddingEnd = UNDEFINED_PADDING;
        Rect localInsets = sThreadLocal.get();
        if (localInsets == null) {
            localInsets = new Rect();
            sThreadLocal.set(localInsets);
        }
        boolean res = computeFitSystemWindows(insets, localInsets);
        mUserPaddingLeftInitial = localInsets.left;
        mUserPaddingRightInitial = localInsets.right;
        internalSetPadding(localInsets.left, localInsets.top,
                localInsets.right, localInsets.bottom);
        return res;
    }
    return false;
}

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

В документации ViewCompat.javaдля setFitsSystemWindowsговорится:

Устанавливает, должно ли это представление учитывать художественные оформления системного экрана, такие как строка состояния, и вставлять ее содержимое; то есть контроль того, будет ли выполняться реализация по умолчанию для {@link View # fitSystemWindows (Rect)}. См. Этот метод для получения более подробной информации .

По этому fitsSystemWindowsпросто означает, что функция fitsSystemWindows()будет выполнена? Новые классы материалов, кажется, используют это просто для рисования под строкой состояния. Если мы посмотрим на DrawerLayout.javaкод пользователя, то увидим следующее:

if (ViewCompat.getFitsSystemWindows(this)) {
        IMPL.configureApplyInsets(this);
        mStatusBarBackground = IMPL.getDefaultStatusBarBackground(context);
    }

...

public static void configureApplyInsets(View drawerLayout) {
    if (drawerLayout instanceof DrawerLayoutImpl) {
        drawerLayout.setOnApplyWindowInsetsListener(new InsetsListener());
        drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    }
}

И мы видим тот же образец в новом CoordinatorLayoutили AppBarLayout.

Разве это не работает прямо противоположно документации fitsSystemWindows? В последних случаях это означает рисование за решеткой системы .

Однако, если вы хотите, чтобы a FrameLayoutотображался за строкой состояния, установка значения fitsSystemWindowstrue не поможет, поскольку реализация по умолчанию выполняет то, что задокументировано изначально. Вы должны переопределить его и добавить те же флаги, что и другие упомянутые классы. Я что-то упускаю?

Штырь
источник
1
Это похоже на ошибку, я опубликовал отчет об ошибке в системе отслеживания проблем Android
Тим Рэй
1
Проверьте здесь: medium.com/google-developers/…
Fatih S.
Спасибо за ссылку, очень полезно. Тем не менее, это подтверждает, что там есть несоответствия. На связанной странице говорится, что некоторые из новых виджетов, например CoordinatorLayout, используют этот флаг, чтобы определить, должны ли они рисовать за строкой состояния или нет. Это FrameLayout, например, не так.
Пин
2
Это был отличный вопрос и очень хорошая работа по изучению исходного кода Android. Мне особенно понравилось, что вы определили, как новые MD-классы по-разному подходят к SystemWindows .... Я сошел с ума, пытаясь понять это!
coolDude

Ответы:

19

Системные окна - это части экрана, на которых система рисует либо неинтерактивное (в случае строки состояния), либо интерактивное (в случае панели навигации) содержимое.

В большинстве случаев вашему приложению не нужно рисовать под строкой состояния или панелью навигации, но если вы это сделаете: вам нужно убедиться, что интерактивные элементы (например, кнопки) не скрыты под ними. Это то, что дает вам стандартное поведение атрибута android: fitsSystemWindows = «true»: он устанавливает отступ для представления, чтобы гарантировать, что содержимое не перекрывает системные окна.

https://medium.com/google-developers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec

iljyya
источник
1
Хорошо, я понимаю
MJ Studio
6

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

Hala.M
источник