O problema básico é que você precisa aguardar a fase de desenho para as medições reais (especialmente com valores dinâmicos como wrap_content
ou match_parent
), mas geralmente essa fase ainda não foi concluída onResume()
. Portanto, você precisa de uma solução alternativa para aguardar essa fase. Existem diferentes soluções possíveis para isso:
1. Ouça eventos de desenho / layout: ViewTreeObserver
Um ViewTreeObserver é acionado para diferentes eventos de desenho. Normalmente, OnGlobalLayoutListener
é isso que você deseja para obter a medição, para que o código no ouvinte seja chamado após a fase de layout, para que as medidas estejam prontas:
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
view.getHeight(); //height is ready
}
});
Nota: O ouvinte será removido imediatamente, caso contrário, será acionado em todos os eventos de layout. Se você precisar oferecer suporte a aplicativos SDK Nvl <16, use-o para cancelar o registro do ouvinte:
public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)
2. Adicione um executável à fila de layout: View.post ()
Não é muito conhecido e minha solução favorita. Basicamente, basta usar o método de postagem do View com seu próprio executável. Isso basicamente enfileira seu código após a medida, o layout etc. da exibição, conforme declarado por Romain Guy :
A fila de eventos da interface do usuário processará os eventos em ordem. Depois que setContentView () for chamado, a fila de eventos conterá uma mensagem solicitando uma retransmissão; portanto, tudo o que você postar na fila acontecerá após a aprovação do layout
Exemplo:
final View view=//smth;
...
view.post(new Runnable() {
@Override
public void run() {
view.getHeight(); //height is ready
}
});
A vantagem sobre ViewTreeObserver
:
- seu código é executado apenas uma vez e você não precisa desativar o Observer após a execução, o que pode ser um aborrecimento
- sintaxe menos detalhada
Referências:
3. Substituir o método onLayout do Views
Isso é prático apenas em determinadas situações em que a lógica pode ser encapsulada na própria exibição, caso contrário, essa é uma sintaxe bastante detalhada e complicada.
view = new View(this) {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
view.getHeight(); //height is ready
}
};
Lembre-se também de que onLayout será chamado várias vezes; portanto, considere o que você faz no método ou desative seu código após a primeira vez.
4. Verifique se passou pela fase de layout
Se você tiver um código executando várias vezes ao criar a interface do usuário, poderá usar o seguinte método de suporte v4 lib:
View viewYouNeedHeightFrom = ...
...
if(ViewCompat.isLaidOut(viewYouNeedHeightFrom)) {
viewYouNeedHeightFrom.getHeight();
}
Retorna true se a visualização passou por pelo menos um layout desde a última vez que foi anexada ou desanexada de uma janela.
Adicional: Obtendo medidas definidas estática
Se basta obter a altura / largura definida estaticamente, você pode fazer isso com:
Mas lembre-se de que isso pode ser diferente da largura / altura real após o desenho. O javadoc descreve a diferença perfeitamente:
O tamanho de uma vista é expresso com uma largura e uma altura. Uma vista possui realmente dois pares de valores de largura e altura.
O primeiro par é conhecido como largura e altura medidas. Essas dimensões definem o tamanho que uma exibição deseja ter dentro de seu pai (consulte Layout para obter mais detalhes.) As dimensões medidas podem ser obtidas chamando getMeasuredWidth () e getMeasuredHeight ().
O segundo par é simplesmente conhecido como largura e altura, ou às vezes largura e altura do desenho. Essas dimensões definem o tamanho real da vista na tela, no tempo de desenho e após o layout. Esses valores podem, mas não precisam, ser diferentes da largura e altura medidas. A largura e a altura podem ser obtidas chamando getWidth () e getHeight ().