O que exatamente o fitsSystemWindows faz?

126

Estou lutando para entender o conceito de fitsSystemWindowsque, dependendo da visão, ele faz coisas diferentes. De acordo com a documentação oficial, é uma

Atributo interno booleano para ajustar o layout da vista com base nas janelas do sistema, como a barra de status. Se verdadeiro, ajusta o preenchimento dessa visualização para deixar espaço para as janelas do sistema .

Agora, verificando a View.javaclasse, vejo que, quando definido como true, as inserções da janela (barra de status, barra de navegação ...) são aplicadas aos campos de visualização, que funcionam de acordo com a documentação citada acima. Esta é a parte relevante do código:

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

Com o novo design de material, há novas classes que fazem uso extensivo dessa bandeira e é aí que entra a confusão. Em muitas fontes, fitsSystemWindowsé mencionado como o sinalizador a ser definido para colocar a visualização atrás das barras do sistema. Veja aqui .

A documentação em ViewCompat.javafor setFitsSystemWindowsdiz:

Define se essa visualização deve ou não levar em conta as decorações da tela do sistema, como a barra de status, e inserir seu conteúdo; isto é, controlar se a implementação padrão do {@link View # fitSystemWindows (Rect)} será executada. Veja esse método para mais detalhes .

De acordo com isso, fitsSystemWindowssignifica simplesmente que a função fitsSystemWindows()será executada? As novas classes de materiais parecem usar isso apenas para desenhar na barra de status. Se olharmos para DrawerLayout.javao código, podemos ver o seguinte:

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

E vemos o mesmo padrão no novo CoordinatorLayoutou AppBarLayout.

Isso não funciona exatamente da maneira oposta à documentação fitsSystemWindows? Nos últimos casos, significa desenhar atrás das barras do sistema .

No entanto, se você quiser FrameLayoutse destacar atrás da barra de status, definir fitsSystemWindowscomo true não funciona, como a implementação padrão faz o que está documentado inicialmente. Você deve substituí-lo e adicionar os mesmos sinalizadores que as outras classes mencionadas. Estou esquecendo de algo?

PIN
fonte
1
Este parece ser um bug, eu postei um relatório de bug no issue tracker Android
Tim Rae
1
Verifique aqui: medium.com/google-developers/…
Fatih S.
Obrigado pelo link, muito útil. Ainda assim, confirma que existem inconsistências lá. Na página vinculada, diz que alguns dos novos widgets, como CoordinatorLayout, usam esse sinalizador para inferir se devem pintar atrás da barra de status ou não. Não é esse o caso FrameLayout, por exemplo.
Pin
2
Essa foi uma ótima pergunta e um trabalho muito bom investigando o código-fonte do Android. Apreciei particularmente que você identificou como as novas classes MD lidam com o SystemWindows de maneira diferente ... Eu estava ficando louco tentando descobrir isso!
cooldude

Respostas:

19

Janelas do sistema são as partes da tela em que o sistema está desenhando conteúdo não interativo (no caso da barra de status) ou interativo (no caso da barra de navegação).

Na maioria das vezes, seu aplicativo não precisará desenhar sob a barra de status ou na barra de navegação, mas se você precisar: verifique se os elementos interativos (como botões) não ficam ocultos por baixo deles. É isso que o comportamento padrão do android: o atributo fitsSystemWindows = "true" fornece: ele define o preenchimento da tela para garantir que o conteúdo não se sobreponha às janelas do sistema.

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

iljyya
fonte
1
Ok, eu entendo
MJ Studio
6

ele não desenha atrás da barra do sistema, estica-se atrás da barra para tingir-a com as mesmas cores que possui, mas as vistas que ela contém são preenchidas dentro da barra de status, se isso faz sentido

Hala.M
fonte