Wyjaśnienie widoku niestandardowego onMeasure
Próbowałem zrobić niestandardowy komponent. Rozszerzyłem klasę View
i wykonałem rysowanie w onDraw
overrided method. Dlaczego muszę nadpisać onMeasure
? Jeśli nie, wszystko będzie dobrze. Czy ktoś może to wyjaśnić? Jak napisać moją metodę onMeasure
? Widziałem kilka samouczków, ale każdy z nich jest trochę inny niż drugi. Czasami dzwonią super.onMeasure
na końcu, czasami używają setMeasuredDimension
i nie dzwonią. Gdzie jest różnica?
W końcu chcę użyć kilku dokładnie tych samych komponenty. Dodałem te komponenty do pliku XML
, ale nie wiem, jak duże powinny być. Chcę ustawić jego pozycję i rozmiar później (dlaczego muszę ustawić rozmiar w onMeasure
jeśli w {[1] } Kiedy rysuję, działa również) w niestandardowej klasie komponentów. Kiedy dokładnie mam to zrobić?
2 answers
onMeasure()
jest to Twoja okazja, aby powiedzieć Androidowi, jak duży chcesz, aby Twój niestandardowy widok był zależny od ograniczeń układu dostarczonych przez rodzica; jest to również okazja Twojego niestandardowego widoku, aby dowiedzieć się, jakie są te ograniczenia układu (w przypadku, gdy chcesz zachowywać się inaczej w sytuacji match_parent
niż w sytuacji wrap_content
). Ograniczenia te są pakowane do wartości MeasureSpec
, które są przekazywane do metody. Oto przybliżona korelacja wartości trybu:
-
dokładnie oznacza, że wartość
layout_width
lublayout_height
została ustawiona na określoną wartość. Powinieneś zrobić swój widok w takim rozmiarze. Może to być również wywołane, gdymatch_parent
jest używany, aby ustawić rozmiar dokładnie do widoku nadrzędnego (jest to zależne od układu w frameworku). -
AT_MOST zazwyczaj oznacza, że wartość
layout_width
lublayout_height
została ustawiona namatch_parent
lubwrap_content
, gdzie wymagany jest maksymalny rozmiar (jest to zależne od układu w strukturze), a rozmiar nadrzędnego wymiaru jest wartością. Nie powinieneś być żadnym większy niż ten rozmiar. -
nieokreślona zazwyczaj oznacza, że wartość
layout_width
lublayout_height
została ustawiona nawrap_content
bez ograniczeń. Możesz mieć dowolny rozmiar. Niektóre układy używają również tego połączenia zwrotnego, aby dowiedzieć się pożądanego rozmiaru, zanim określisz, jakie specyfikacje faktycznie przekażą cię ponownie w drugim żądaniu pomiaru.
Umowa, która istnieje z onMeasure()
jest taka, że setMeasuredDimension()
musi być wywołane na końcu z rozmiarem, jaki chcesz mieć widok. To metoda jest wywoływana przez wszystkie implementacje frameworka, w tym domyślną implementację znajdującą się w View
, dlatego bezpieczne jest wywołanie super
, jeśli pasuje to do twojego przypadku użycia.
Przyznane, ponieważ framework stosuje 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ż zawartość, jeśli tego nie zrobisz, i jeśli ułożysz swój niestandardowy widok za pomocą wrap_content
w obu kierunkach, twój widok będzie wyświetlany może się w ogóle nie pojawić, ponieważ framework nie wie, jak duży jest!
Ogólnie rzecz biorąc, jeśli nadpisujesz View
, a nie inny istniejący widżet, prawdopodobnie dobrym pomysłem jest dostarczenie implementacji, nawet jeśli jest to tak proste, 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 pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-17 14:46:51
W rzeczywistości odpowiedź nie jest kompletna, ponieważ wartości zależą również od kontenera. W przypadku układów względnych lub liniowych wartości zachowują się następująco:
- Dokładnie match_parent jest dokładnie + rozmiar rodzica
- AT_MOST wrap_content daje wynik At_most MeasureSpec
- nieokreślone nigdy nie wyzwalane
W przypadku poziomego przewijania kod będzie działał.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-30 07:42:28