Qual é a maneira correta de substituir onMeasure ()? Já vi várias abordagens. Por exemplo, o Professional Android Development usa MeasureSpec para calcular as dimensões e termina com uma chamada para setMeasuredDimension (). Por exemplo:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth/2, parentHeight);
}
Por outro lado, de acordo com esta postagem , a maneira "correta" é usar MeasureSpec, chamar setMeasuredDimensions (), seguido por uma chamada para setLayoutParams () e terminar com uma chamada para super.onMeasure (). Por exemplo:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth/2, parentHeight);
this.setLayoutParams(new *ParentLayoutType*.LayoutParams(parentWidth/2,parentHeight));
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Então, qual é o caminho certo? Nenhuma das abordagens funcionou 100% para mim.
Acho que realmente o que estou perguntando é: alguém conhece um tutorial que explica onMeasure (), layout, dimensões das visualizações filho etc.?
android
android-layout
U Avalos
fonte
fonte
Respostas:
As outras soluções não são abrangentes. Eles podem funcionar em alguns casos e são um bom lugar para começar, mas podem não ter garantia de funcionamento.
Quando onMeasure é chamado, você pode ou não ter o direito de alterar o tamanho. Os valores que são passados para seu onMeasure (
widthMeasureSpec
,heightMeasureSpec
) contêm informações sobre o que sua visualização secundária tem permissão para fazer. Atualmente, existem três valores:MeasureSpec.UNSPECIFIED
- Você pode ser tão grande quanto quiserMeasureSpec.AT_MOST
- Tão grande quanto você quiser (até o tamanho das especificações), este é oparentWidth
seu exemplo.MeasureSpec.EXACTLY
- Sem escolha. O pai escolheu.Isso é feito para que o Android possa fazer várias passagens para encontrar o tamanho certo para cada item, veja aqui para mais detalhes.
Se você não seguir essas regras, não há garantia de que sua abordagem funcione.
Por exemplo, se você deseja verificar se tem permissão para alterar o tamanho, você pode fazer o seguinte:
Usando essas informações, você saberá se pode modificar os valores como em seu código. Ou se você for obrigado a fazer algo diferente. Uma maneira rápida e fácil de determinar o tamanho desejado é usar um dos seguintes métodos:
int resolveSizeAndState (int size, int measureSpec, int childMeasuredState)
int resolveSize (int size, int measureSpec)
Enquanto o primeiro está disponível apenas no Honeycomb, o segundo está disponível em todas as versões.
Nota: você pode achar que
resizeWidth
ouresizeHeight
são sempre falsos. Eu descobri que esse era o caso, se eu estivesse solicitandoMATCH_PARENT
. Consegui corrigir isso solicitandoWRAP_CONTENT
no layout pai e, durante a fase NÃO ESPECIFICADA, solicitando um tamanho deInteger.MAX_VALUE
. Isso fornece o tamanho máximo que seus pais permitem na próxima passagem por onMeasure.fonte
A documentação é a autoridade neste assunto: http://developer.android.com/guide/topics/ui/how-android-draws.html e http://developer.android.com/guide/topics/ui/custom -components.html
Para resumir: no final do seu
onMeasure
método substituído , você deve chamarsetMeasuredDimension
.Você não deve ligar
super.onMeasure
após ligarsetMeasuredDimension
, isso apenas apagará tudo o que você definiu. Em algumas situações, você pode querer chamar osuper.onMeasure
primeiro e depois modificar os resultados chamandosetMeasuredDimension
.Não chame
setLayoutParams
noonMeasure
. O layout acontece em uma segunda passagem após a medição.fonte
Acho que depende do pai o que você está substituindo.
Por exemplo, se você está estendendo um ViewGroup (como FrameLayout), quando você mediu o tamanho, você deve chamar como abaixo
porque você pode querer que o ViewGroup faça o trabalho de descanso (faça algumas coisas na visualização infantil)
Se você estiver estendendo uma View (como ImageView), você pode simplesmente chamar
this.setMeasuredDimension(width, height);
, porque a classe pai fará algo como você normalmente faz.Em uma palavra, se você quiser alguns recursos que sua classe pai oferece gratuitamente, você deve ligar
super.onMeasure()
(passar a especificação de medida de modo MeasureSpec.EXACTLY normalmente), caso contrário,this.setMeasuredDimension(width, height);
basta ligar .fonte
aqui está como resolvi o problema:
}
Além disso, era necessário que o componente ViewPager
fonte
super.onMeasure
irá limpar as dimensões definidas usandosetMeasuredDimension
.Se mudar o tamanho das visualizações dentro de
onMeasure
tudo que você precisa é asetMeasuredDimension
chamada. Se você estiver mudando o tamanho fora deonMeasure
você precisa ligarsetLayoutParams
. Por exemplo, alterar o tamanho de uma visualização de texto quando o texto é alterado.fonte
Depende do controle que você está usando. As instruções na documentação funcionam para alguns controles (TextView, Button, ...), mas não para outros (LinearLayout, ...). A maneira que funcionou muito bem para mim foi ligar para o zelador assim que terminar. Com base no artigo no link abaixo.
http://humptydevelopers.blogspot.in/2013/05/android-view-overriding-onmeasure.html
fonte
Eu acho que setLayoutParams e recalcular as medidas é uma solução alternativa para redimensionar as visualizações filho corretamente, pois isso geralmente é feito no onMeasure da classe derivada.
No entanto, isso raramente funciona corretamente (por qualquer motivo ...), é melhor chamar measureChildren (ao derivar um ViewGroup) ou tentar algo semelhante quando necessário.
fonte
você pode pegar este pedaço de código como um exemplo de onMeasure () ::
fonte