Eu tenho uma visão composta TableLayout, TableRow and TextView
. Quero que pareça uma grade. Preciso obter a altura e a largura dessa grade. Os métodos getHeight()
e getWidth()
sempre retornam 0. Isso acontece quando eu formato a grade dinamicamente e também quando uso uma versão XML.
Como recuperar as dimensões para uma vista?
Aqui está o meu programa de teste que usei no Debug para verificar os resultados:
import android.app.Activity;
import android.os.Bundle;
import android.widget.TableLayout;
import android.widget.TextView;
public class appwig extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.maindemo); //<- includes the grid called "board"
int vh = 0;
int vw = 0;
//Test-1 used the xml layout (which is displayed on the screen):
TableLayout tl = (TableLayout) findViewById(R.id.board);
tl = (TableLayout) findViewById(R.id.board);
vh = tl.getHeight(); //<- getHeight returned 0, Why?
vw = tl.getWidth(); //<- getWidth returned 0, Why?
//Test-2 used a simple dynamically generated view:
TextView tv = new TextView(this);
tv.setHeight(20);
tv.setWidth(20);
vh = tv.getHeight(); //<- getHeight returned 0, Why?
vw = tv.getWidth(); //<- getWidth returned 0, Why?
} //eof method
} //eof class
getHeight()
egetWidth()
depois que o ciclo de vida da atividade solicitar que os pontos de vista se medam, em outras palavras, faça esse tipo de coisaonResume()
e pronto. Você não deve esperar que um objeto ainda não definido conheça suas dimensões, esse é o truque. Não há necessidade da mágica sugerida abaixo.getHeight()/Width()
emonResume()
não deu> 0 valor para mim.Respostas:
Acredito que o OP já se foi há muito tempo, mas, caso essa resposta possa ajudar futuros pesquisadores, pensei em publicar uma solução que encontrei. Eu adicionei este código no meu
onCreate()
método:EDITADO: 07/05/11 para incluir o código dos comentários:
Primeiro, recebo uma referência final ao meu
TextView
(para acessar noonGlobalLayout()
método). Em seguida, obtenho o valorViewTreeObserver
de meuTextView
e adiciono umaOnGlobalLayoutListener
substituiçãoonGLobalLayout
(não parece haver um método de superclasse para chamar aqui ...) e adiciono meu código que requer conhecer as medidas da exibição nesse ouvinte. Tudo funciona como esperado para mim, então espero que isso possa ajudar.fonte
tv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
dessa maneira, o ouvinte deve ser removido após a primeira vez ocorre.addOnLayoutChangeListener
funciona! :)Vou apenas adicionar uma solução alternativa, substituir o método onWindowFocusChanged da sua atividade e você poderá obter os valores de getHeight (), getWidth () a partir daí.
fonte
ViewTreeObserver
.Você está tentando obter a largura e a altura de um elemento que ainda não foi desenhado.
Se você usar depuração e parar em algum momento, verá que a tela do seu dispositivo ainda está vazia, porque seus elementos ainda não foram desenhados, portanto você não pode obter a largura e a altura de algo que ainda não existir.
E, eu posso estar errado, mas
setWidth()
nem sempre é respeitado,Layout
define seus filhos e decide como medi-los (chamandochild.measure()
); portanto, se você definirsetWidth()
, não terá garantia de obter essa largura após o elemento ser desenhado.O que você precisa é usar
getMeasuredWidth()
(a medida mais recente da sua Visualização) em algum lugar após a visualização ter sido realmente desenhada.Examine o
Activity
ciclo de vida para encontrar o melhor momento.http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
Acredito que uma boa prática é usar
OnGlobalLayoutListener
assim:Você pode inserir esse código diretamente
onCreate()
e ele será chamado quando as visualizações forem dispostas.fonte
Use o método de postagem da View como este
fonte
Tentei usar
onGlobalLayout()
uma formatação personalizada de aTextView
, mas como @George Bailey notou, naonGlobalLayout()
verdade é chamado duas vezes: uma vez no caminho de layout inicial e segunda após a modificação do texto.View.onSizeChanged()
funciona melhor para mim porque, se eu modificar o texto, o método será chamado apenas uma vez (durante a passagem do layout). Essa subclassificação necessária deTextView
, mas no nível 11 da API,View. addOnLayoutChangeListener()
pode ser usada para evitar subclassificações.Mais uma coisa, para obter a largura correta da visualização
View.onSizeChanged()
,layout_width
deve ser definido comomatch_parent
, nãowrap_content
.fonte
Você está tentando obter tamanhos em um construtor ou qualquer outro método executado antes de obter a imagem real?
Você não obterá nenhuma dimensão antes que todos os componentes sejam realmente medidos (já que o seu XML não sabe sobre o tamanho da tela, a posição dos pais e o que for)
Tente obter valores após onSizeChanged () (embora possa ser chamado com zero) ou simplesmente aguarde quando você obtém uma imagem real.
fonte
Como o FX mencionou, você pode usar um
OnLayoutChangeListener
para a visualização que deseja rastrearVocê pode remover o ouvinte no retorno de chamada se desejar apenas o layout inicial.
fonte
Eu acho que é isso que você precisa olhar: uso
onSizeChanged()
da sua visão. Aqui está um trecho de código EXTENDED sobre como usaronSizeChanged()
para obter a altura e a largura do seu layout ou da visualização dinamicamente http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.htmlfonte
ViewTreeObserver
eonWindowFocusChanged()
não são tão necessários.Se você inflar o
TextView
layout as e / ou colocar algum conteúdo nele e definirLayoutParams
, poderá usargetMeasuredHeight()
egetMeasuredWidth()
.MAS você tem que ter cuidado com
LinearLayouts
(talvez também com outrosViewGroups
). O problema é que você pode obter a largura e a altura depois,onWindowFocusChanged()
mas se tentar adicionar algumas visualizações, não poderá obter essas informações até que tudo tenha sido desenhado. Eu estava tentando adicionar váriosTextViews
paraLinearLayouts
imitar umFlowLayout
(estilo de quebra) e, portanto, não podia usarListeners
. Depois que o processo é iniciado, ele deve continuar de forma síncrona. Portanto, nesse caso, convém manter a largura em uma variável para usá-la posteriormente, pois, ao adicionar visualizações ao layout, você poderá precisar.fonte
Embora a solução proposta funcione, ela pode não ser a melhor solução para todos os casos, porque com base na documentação para
ViewTreeObserver.OnGlobalLayoutListener
o que significa que é chamado muitas vezes e nem sempre a vista é medida (tem altura e largura determinadas)
Uma alternativa é usar o
ViewTreeObserver.OnPreDrawListener
que é chamado apenas quando a vista está pronta para ser desenhada e tem todas as suas medidas.fonte
Você deve observar o ciclo de vida do View: http://developer.android.com/reference/android/view/View.html Geralmente, você não deve saber a largura e a altura com certeza até que sua atividade chegue ao estado onResume.
fonte
Você pode usar uma transmissão chamada OnResume ()
Por exemplo:
Você não pode obter a altura de uma exibição em OnCreate (), onStart () ou mesmo em onResume () pelo motivo pelo qual o kcoppock respondeu
fonte
A altura e a largura são zero porque a visualização não foi criada no momento em que você solicita sua altura e largura. Uma solução mais simples é
Este método é bom em comparação com outros métodos, pois é curto e nítido.
fonte
Resposta simples: Isso funcionou para mim sem nenhum problema. Parece que a chave é garantir que o View tenha foco antes de getHeight etc. Faça isso usando o método hasFocus () e, em seguida, usando o método getHeight () nessa ordem. São necessárias apenas 3 linhas de código.
ImageButton myImageButton1 =(ImageButton)findViewById(R.id.imageButton1);
myImageButton1.hasFocus();
int myButtonHeight = myImageButton1.getHeight();
Log.d("Button Height: ", ""+myButtonHeight );//Not required
Espero que ajude.
fonte
Use getMeasuredWidth () e getMeasuredHeight () para sua visualização.
Guia do desenvolvedor: View
fonte
CORREÇÃO: Descobri que a solução acima é terrível. Especialmente quando o telefone está lento. E aqui, encontrei outra solução: calcule o valor de px do elemento, incluindo as margens e os preenchimentos: dp para px: https://stackoverflow.com/a/6327095/1982712
ou dimens.xml para px: https://stackoverflow.com/a/16276351/1982712
sp para px: https://stackoverflow.com/a/9219417/1982712 (reverta a solução)
ou diminui para px: https://stackoverflow.com/a/16276351/1982712
e é isso.
fonte