onMeasure()
to okazja, by powiedzieć Androidowi, jak duży ma być twój niestandardowy widok od ograniczeń układu dostarczonych przez rodzica; jest to również okazja, aby w widoku niestandardowym dowiedzieć się, jakie są ograniczenia układu (w przypadku, gdy chcesz zachowywać się inaczej w match_parent
sytuacji niż w wrap_content
sytuacji). Ograniczenia te są pakowane w MeasureSpec
wartości przekazywane do metody. Oto przybliżona korelacja wartości trybu:
- DOKŁADNIE oznacza, że wartość
layout_width
lub layout_height
została ustawiona na określoną wartość. Prawdopodobnie powinieneś zrobić widok tego rozmiaru. Można to również uruchomić, gdy match_parent
jest używane, aby ustawić rozmiar dokładnie w widoku nadrzędnym (jest to zależne od układu w ramach).
- AT_MOST zazwyczaj oznacza, że wartość
layout_width
lub layout_height
została ustawiona na match_parent
lub wrap_content
tam, gdzie potrzebny jest maksymalny rozmiar (jest to zależne od układu w strukturze), a rozmiar wymiaru nadrzędnego jest wartością. Nie powinieneś być większy niż ten rozmiar.
- NIEPECYFIKOWANE zazwyczaj oznacza, że wartość
layout_width
lub layout_height
została ustawiona wrap_content
bez żadnych ograniczeń. Możesz mieć dowolną wielkość. Niektóre układy również używają tego wywołania zwrotnego, aby ustalić pożądany rozmiar przed określeniem, jakie specyfikacje faktycznie przekazać ponownie w żądaniu drugiego pomiaru.
Umowa, która istnieje onMeasure()
, setMeasuredDimension()
MUSI być wywoływana na końcu z rozmiarem, jaki chcesz mieć widok. Ta metoda jest wywoływana przez wszystkie implementacje frameworka, w tym implementację domyślną znalezioną w View
, dlatego można bezpiecznie wywoływać super
zamiast tego, jeśli pasuje to do twojego przypadku użycia.
To prawda, że ponieważ struktura ma domyślną implementację, może nie być konieczne zastąpienie tej metody, ale możesz zobaczyć obcinanie w przypadkach, gdy przestrzeń widoku jest mniejsza niż treść, jeśli nie, i jeśli rozłożysz widok niestandardowy wrap_content
w obu kierunkach może wcale nie być wyświetlany, ponieważ struktura nie wie, jak duży jest!
Ogólnie rzecz biorąc, jeśli przesłonisz, View
a nie inny istniejący widget, prawdopodobnie dobrym pomysłem jest zapewnienie implementacji, nawet jeśli jest tak prosta jak coś takiego:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = 100;
int desiredHeight = 100;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(width, height);
}
Mam nadzieję, że to pomaga.
View
klasie są metody pomocnicze , nazywaneresolveSizeAndState
iresolveSize
, które powinny robić to, co robią klauzule „if” - uznałem je za przydatne, szczególnie jeśli trzeba często pisać te IF.twoja odpowiedź nie jest kompletna, ponieważ wartości zależą również od opakowania. W przypadku układów względnych lub liniowych wartości zachowują się w następujący sposób:
W przypadku przewijania w poziomie kod będzie działał.
źródło
Jeśli nie musisz nic zmieniać w Pomiarze - absolutnie nie musisz tego zastępować.
Kod Devunwired (tutaj wybrana i najczęściej głosowana odpowiedź) jest prawie identyczny z tym, co już dla ciebie zrobiła implementacja SDK (i sprawdziłem - zrobiło to od 2009 roku).
Możesz sprawdzić metodę onMeasure tutaj :
Przesłanianie kodu SDK, który ma zostać zastąpiony dokładnie tym samym kodem, nie ma sensu.
Ten oficjalny dokument, który twierdzi, że „domyślna właściwość onMeasure () zawsze ustawia rozmiar 100 x 100” - jest błędna.
źródło