Mam pogląd złożony z TableLayout, TableRow and TextView
. Chcę, żeby to wyglądało jak siatka. Muszę uzyskać wysokość i szerokość tej siatki. Metody getHeight()
i getWidth()
zawsze zwracają 0. Dzieje się tak, gdy dynamicznie formatuję siatkę, a także gdy używam wersji XML.
Jak odzyskać wymiary widoku?
Oto mój program testowy, którego użyłem w Debugowaniu do sprawdzenia wyników:
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()
agetWidth()
po zakończeniu cyklu życia Aktywności poprosił opinie, żeby się zmierzyły, innymi słowy, robią tego rodzaju rzeczyonResume()
i to wszystko. Nie należy oczekiwać, że jeszcze nie rozplanowany obiekt pozna jego wymiary, to cała sztuczka. Nie ma potrzeby używania magii sugerowanej poniżej.getHeight()/Width()
wonResume()
nie dały> 0 wartość dla mnie.Odpowiedzi:
Wierzę, że PO już dawno minęło, ale na wypadek gdyby ta odpowiedź była w stanie pomóc przyszłym poszukiwaczom, pomyślałem, że opublikuję znalezione rozwiązanie. Dodałem ten kod do mojej
onCreate()
metody:ZMIENIONO: 07.05.11, aby dołączyć kod z komentarzy:
Najpierw otrzymuję ostateczne odniesienie do mojego
TextView
(aby uzyskać dostęp wonGlobalLayout()
metodzie). Następnie pobieramViewTreeObserver
od siebieTextView
i dodamOnGlobalLayoutListener
przesłonięcieonGLobalLayout
(wydaje się , że nie ma tu metody nadklasy do wywołania tutaj ...) i dodanie mojego kodu, który wymaga znajomości pomiarów widoku dla tego odbiornika. Wszystko działa zgodnie z oczekiwaniami, więc mam nadzieję, że to pomoże.źródło
tv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
ten sposób słuchacz powinien zostać usunięty po raz pierwszy Pojawia się.addOnLayoutChangeListener
działa! :)Dodam tylko alternatywne rozwiązanie, zastąpię metodę onWindowFocusChanged twojej aktywności, a stamtąd będziesz mógł uzyskać wartości getHeight (), getWidth ().
źródło
ViewTreeObserver
.Próbujesz uzyskać szerokość i wysokość elementów, które nie zostały jeszcze narysowane.
Jeśli użyjesz debugowania i zatrzymasz się w pewnym momencie, zobaczysz, że ekran Twojego urządzenia jest nadal pusty, to dlatego, że twoje elementy nie zostały jeszcze narysowane, więc nie możesz uzyskać szerokości i wysokości czegoś, co jeszcze nie istnieć.
I mogę się mylić, ale
setWidth()
nie zawsze jestem szanowany,Layout
określa, że są to dzieci i decyduje, jak je mierzyć (dzwonićchild.measure()
), więc jeśli ustawiszsetWidth()
, nie będziesz mieć gwarancji, że uzyskasz tę szerokość po narysowaniu elementu.Czego potrzebujesz, to użyć
getMeasuredWidth()
(najnowszej miary swojego widoku) gdzieś po tym, jak widok został narysowany.Zbadać
Activity
cykl życia, aby znaleźć najlepszy moment.http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
Uważam, że dobrą praktyką jest używanie w
OnGlobalLayoutListener
ten sposób:Możesz umieścić ten kod bezpośrednio w nim
onCreate()
, a zostanie on wywołany, gdy zostaną utworzone widoki.źródło
Skorzystaj z metody postu Widoku w ten sposób
źródło
Próbowałem użyć
onGlobalLayout()
niestandardowego formatowania aTextView
, ale jak zauważył @George Bailey,onGlobalLayout()
tak naprawdę jest on wywoływany dwukrotnie: raz na początkowej ścieżce układu i drugi raz po zmodyfikowaniu tekstu.View.onSizeChanged()
działa dla mnie lepiej, ponieważ jeśli tam zmodyfikuję tekst, metoda jest wywoływana tylko raz (podczas przejścia układu). Wymagało to podklasyTextView
, ale na poziomie API 11+View. addOnLayoutChangeListener()
można użyć, aby uniknąć podklasy.Jeszcze jedna rzecz, aby uzyskać poprawną szerokość widoku
View.onSizeChanged()
,layout_width
należy ustawić namatch_parent
niewrap_content
.źródło
Czy próbujesz uzyskać rozmiary w konstruktorze, czy jakąkolwiek inną metodę, która jest uruchamiana PRZED uzyskaniem rzeczywistego obrazu?
Nie otrzymasz żadnych wymiarów, zanim wszystkie składniki nie zostaną zmierzone (ponieważ twój plik xml nie wie o twoim rozmiarze wyświetlacza, pozycjach rodziców i tym podobnych)
Spróbuj uzyskać wartości po onSizeChanged () (choć można go wywołać zerem) lub po prostu poczekaj, aż otrzymasz rzeczywisty obraz.
źródło
Jak wspomniano FX, możesz użyć
OnLayoutChangeListener
widoku, który chcesz śledzićMożesz usunąć detektor w wywołaniu zwrotnym, jeśli chcesz tylko początkowy układ.
źródło
Chyba właśnie na to trzeba spojrzeć: wykorzystanie
onSizeChanged()
swojego widoku. Oto fragment kodu ROZSZERZONEGO, w jaki sposóbonSizeChanged()
dynamicznie uzyskiwać wysokość i szerokość układu lub widoku http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.htmlźródło
ViewTreeObserver
ionWindowFocusChanged()
wcale nie są tak potrzebne.Jeśli nadmuchasz
TextView
układ jako i / lub umieścisz w nim trochę treści i ustawiszLayoutParams
, możesz użyćgetMeasuredHeight()
igetMeasuredWidth()
.ALE musisz być ostrożny z
LinearLayouts
(może także innymiViewGroups
). Problem polega na tym, że możesz uzyskać szerokość i wysokość później,onWindowFocusChanged()
ale jeśli spróbujesz dodać w niej niektóre widoki, nie możesz uzyskać tych informacji, dopóki wszystko nie zostanie narysowane. Próbowałem dodać wielokrotność,TextViews
abyLinearLayouts
naśladowaćFlowLayout
(styl owijania), więc nie mogłem użyćListeners
. Po uruchomieniu proces powinien być kontynuowany synchronicznie. W takim przypadku możesz chcieć zachować szerokość w zmiennej, aby użyć jej później, ponieważ podczas dodawania widoków do układu możesz jej potrzebować.źródło
Mimo że proponowane rozwiązanie działa, może nie być najlepszym rozwiązaniem dla każdego przypadku, ponieważ jest oparte na dokumentacji
ViewTreeObserver.OnGlobalLayoutListener
co oznacza, że jest wywoływany wiele razy i nie zawsze mierzony jest widok (ma określoną wysokość i szerokość)
Alternatywą jest użycie,
ViewTreeObserver.OnPreDrawListener
które wywoływane jest tylko wtedy, gdy widok jest gotowy do narysowania i ma wszystkie swoje pomiary.źródło
Powinieneś raczej spojrzeć na cykl życia Wyświetl: http://developer.android.com/reference/android/view/View.html Zasadniczo nie powinieneś na pewno znać szerokości i wysokości, dopóki aktywność nie przejdzie w stan wznowienia.
źródło
Możesz użyć transmisji, która jest wywoływana w OnResume ()
Na przykład:
Nie można uzyskać wysokości widoku w OnCreate (), onStart (), a nawet w onResume () z tego powodu, że odpowiedział kcoppock
źródło
Wysokość i szerokość wynoszą zero, ponieważ widok nie został utworzony do momentu, gdy zażądasz jego wysokości i szerokości. Jednym z najprostszych rozwiązań jest
Ta metoda jest dobra w porównaniu do innych metod, ponieważ jest krótka i rześka.
źródło
Prosta odpowiedź: To działało dla mnie bez problemu. Wydaje się, że kluczem jest upewnienie się, że widok ma fokus przed uzyskaniem getHeight itp. Zrób to za pomocą metody hasFocus (), a następnie za pomocą metody getHeight () w tej kolejności. Wymagane są tylko 3 wiersze kodu.
ImageButton myImageButton1 =(ImageButton)findViewById(R.id.imageButton1);
myImageButton1.hasFocus();
int myButtonHeight = myImageButton1.getHeight();
Log.d("Button Height: ", ""+myButtonHeight );//Not required
Mam nadzieję, że to pomoże.
źródło
Użyj getMeasuredWidth () i getMeasuredHeight () dla swojego widoku.
Przewodnik dla programistów: widok
źródło
KOREKTA: Dowiedziałem się, że powyższe rozwiązanie jest okropne. Zwłaszcza, gdy Twój telefon jest wolny. I tutaj znalazłem inne rozwiązanie: oblicz wartość px elementu, w tym marginesów i wypełnień: dp do px: https://stackoverflow.com/a/6327095/1982712
lub dimens.xml na px: https://stackoverflow.com/a/16276351/1982712
sp do px: https://stackoverflow.com/a/9219417/1982712 (odwróć rozwiązanie)
lub dimens do px: https://stackoverflow.com/a/16276351/1982712
i to wszystko.
źródło