Que fait exactement fitSystemWindows?

126

J'ai du mal à comprendre le concept de fitsSystemWindowscomme dépendant de la vue, il fait des choses différentes. Selon la documentation officielle, c'est un

Attribut interne booléen permettant d'ajuster la disposition de la vue en fonction des fenêtres système telles que la barre d'état. Si c'est vrai, ajuste le remplissage de cette vue pour laisser de l'espace pour les fenêtres système .

Maintenant, en vérifiant la View.javaclasse, je peux voir que lorsqu'elle est définie sur true, les encarts de fenêtre (barre d'état, barre de navigation ...) sont appliqués aux paddings de vue, ce qui fonctionne selon la documentation citée ci-dessus. Voici la partie pertinente du code:

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;
}

Avec le nouveau design Material, de nouvelles classes utilisent largement ce drapeau et c'est là que vient la confusion. Dans de nombreuses sources, il fitsSystemWindowsest mentionné comme indicateur à définir pour placer la vue derrière les barres du système. Regardez ici .

La documentation de ViewCompat.javapour setFitsSystemWindowsdit:

Définit si cette vue doit ou non prendre en compte les décorations d'écran du système telles que la barre d'état et insérer son contenu; autrement dit, contrôler si l'implémentation par défaut de {@link View # fitSystemWindows (Rect)} sera exécutée. Voir cette méthode pour plus de détails .

Selon cela, fitsSystemWindowssignifie simplement que la fonction fitsSystemWindows()sera exécutée? Les nouvelles classes de matériaux semblent l'utiliser uniquement pour dessiner sous la barre d'état. Si nous regardons DrawerLayout.javale code de, nous pouvons voir ceci:

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);
    }
}

Et nous voyons le même schéma dans le nouveau CoordinatorLayoutou AppBarLayout.

Cela ne fonctionne-t-il pas exactement à l'opposé de la documentation pour fitsSystemWindows? Dans les derniers cas, cela signifie tirer derrière les barres du système .

Cependant, si vous voulez que un FrameLayoutse dessine derrière la barre d'état, la définition fitsSystemWindowsde true ne fait pas l'affaire car l'implémentation par défaut fait ce qui est documenté initialement. Vous devez le remplacer et ajouter les mêmes indicateurs que les autres classes mentionnées. Est-ce que je manque quelque chose?

Épingle
la source
1
Cela semble être un bogue, j'ai publié un rapport de bogue sur le suivi des problèmes Android
Tim Rae
1
Vérifiez ici: medium.com/google-developers/…
Fatih S.
Merci pour le lien, très utile. Pourtant, cela confirme qu'il y a là des incohérences. Dans la page liée, il est indiqué que certains des nouveaux widgets, tels que CoordinatorLayout, utilisent cet indicateur pour déduire s'ils doivent ou non peindre derrière la barre d'état. Ce n'est pas le cas FrameLayout, par exemple.
Épingler le
2
C'était une excellente question et un très bon travail de recherche dans le code source d'Android. J'ai particulièrement apprécié que vous ayez identifié la manière dont les nouvelles classes MD gèrent différemment FitSystemWindows ... Je devenais fou d'essayer de comprendre cela!
coolDude

Réponses:

19

Les fenêtres système sont les parties de l'écran où le système dessine un contenu non interactif (dans le cas de la barre d'état) ou interactif (dans le cas de la barre de navigation).

La plupart du temps, votre application n'aura pas besoin de dessiner sous la barre d'état ou la barre de navigation, mais si vous le faites: vous devez vous assurer que les éléments interactifs (comme les boutons) ne sont pas cachés en dessous. C'est ce que vous donne le comportement par défaut de l'attribut android: fitsSystemWindows = "true": il définit le remplissage de la vue pour s'assurer que le contenu ne recouvre pas les fenêtres du système.

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

iljyya
la source
1
Ok je comprends
MJ Studio
6

il ne dessine pas derrière la barre système, il s'étire en quelque sorte derrière la barre pour la teinter avec les mêmes couleurs que lui, mais les vues qu'il contient sont remplies à l'intérieur de la barre d'état si cela a du sens

Hala.M
la source