Próbuję uzyskać bezwzględne współrzędne pikseli ekranu w lewym górnym rogu widoku. Jednak wszystkie metody, które mogę znaleźć, takie jak getLeft()
i getRight()
nie działają, ponieważ wszystkie wydają się być względne względem rodzica widoku, co daje mi 0
. Jak to zrobić w odpowiedni sposób?
Jeśli to pomaga, jest to gra „przywróć porządek”. Chcę, aby użytkownik mógł narysować ramkę, aby wybrać wiele elementów. Zakładam, że najłatwiej to zrobić do getRawX()
iz getRawY()
tych, MotionEvent
a następnie porównać te wartości z lewym górnym rogiem układu zawierającego elementy. Znając rozmiar kawałków, mogę ustalić, ile kawałków zostało wybranych. Zdaję sobie sprawę, że mogę używać getX()
i getY()
na MotionEvent
, ale ponieważ to zwraca względną pozycję, która utrudnia ustalenie, które kawałki zostały wybrane. (Wiem, że nie jest to niemożliwe, ale wydaje się to niepotrzebnie skomplikowane).
Edycja: jest to kod, którego użyłem, aby uzyskać rozmiar pojemnika do przechowywania, zgodnie z jednym z pytań. TableLayout
jest stołem, który zawiera wszystkie elementy układanki.
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
Log.d(LOG_TAG, "Values " + tableLayout.getTop() + tableLayout.getLeft());
Edycja 2: Oto kod, który wypróbowałem, podążając za sugerowanymi odpowiedziami.
public int[] tableLayoutCorners = new int[2];
(...)
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
tableLayout.requestLayout();
Rect corners = new Rect();
tableLayout.getLocalVisibleRect(corners);
Log.d(LOG_TAG, "Top left " + corners.top + ", " + corners.left + ", " + corners.right
+ ", " + corners.bottom);
cells[4].getLocationOnScreen(tableLayoutCorners);
Log.d(LOG_TAG, "Values " + tableLayoutCorners[0] + ", " + tableLayoutCorners[1]);
Ten kod został dodany po zakończeniu całej inicjalizacji. Obraz został podzielony na tablicę ImageViews (tablica komórek []) zawartą w TableLayout
. Komórki [0] znajdują się w lewym górnym rogu ImageView
, a ja wybrałem komórki [4], ponieważ są one gdzieś pośrodku i zdecydowanie nie powinny mieć współrzędnych (0,0).
Kod pokazany powyżej wciąż daje mi wszystkie zera w logach, czego tak naprawdę nie rozumiem, ponieważ różne elementy układanki są poprawnie wyświetlane. (Próbowałem public int dla tableLayoutCorners i domyślnej widoczności, obie dały ten sam wynik).
Nie wiem, czy to jest znaczące, ale ImageView
początkowo nie podano rozmiaru. Rozmiar ImageView
s jest określany podczas inicjalizacji automatycznie przez View, gdy daję mu obraz do wyświetlenia. Czy może to przyczynić się do tego, że ich wartości są równe 0, nawet jeśli kod rejestrowania następuje po tym, jak otrzymali obraz i automatycznie zmienili rozmiar? Aby potencjalnie temu przeciwdziałać, dodałem kod tableLayout.requestLayout()
jak pokazano powyżej, ale to nie pomogło.
źródło
Przyjęta odpowiedź tak naprawdę nie powiedziała, jak uzyskać lokalizację, więc tutaj jest trochę więcej szczegółów. Przechodzisz w
int
tablicy o długości 2, a wartości są zastępowane współrzędnymi widoku (x, y) (górnego, lewego rogu).Notatki
getLocationOnScreen
przezgetLocationInWindow
powinno dać takie same wyniki w większości przypadków (patrz ta odpowiedź ). Jeśli jednak znajdujesz się w mniejszym oknie, takim jak okno dialogowe lub klawiatura niestandardowa, użyj go, aby wybrać ten, który najlepiej odpowiada Twoim potrzebom.(0,0)
jeśli wywołasz tę metodę,onCreate
ponieważ widok nie został jeszcze ułożony. Możesz użyć a,ViewTreeObserver
aby nasłuchiwać, kiedy układ jest gotowy, i możesz uzyskać zmierzone współrzędne. (Zobacz tę odpowiedź .)źródło
Najpierw musisz uzyskać lokalny prostokąt Widoku widoku
Na przykład:
Mam nadzieję, że to pomoże
źródło
getGlobalVisibleRect()
dla absolutnych coordów.Korzystanie z globalnego detektora układu zawsze działało dla mnie dobrze. Ma tę zaletę, że może ponownie oceniać rzeczy, jeśli zmieni się układ, np. Jeśli coś jest ustawione na View.GONE lub widoki potomne są dodawane / usuwane.
źródło
setContentView()
spowodował problem w specjalnejActivity
aplikacji! To była aktywność dialogowa (windowFrame:@null, windowActionBar:false, windowIsFloating:true, windowNoTitle:true
). Jego główny układ (aLinearLayout
) nie ma bezpośredniego potomka z określonymlayout_width
(Wszystkie byłymatch_parent
lubwrap_content
).Po komentarzu Romaina Guya, oto jak to naprawiłem. Mam nadzieję, że pomoże to każdemu, kto również miał ten problem.
Rzeczywiście starałem się ustalić pozycje widoków, zanim zostały one rozłożone na ekranie, ale to wcale nie było oczywiste. Te wiersze zostały umieszczone po uruchomieniu kodu inicjującego, więc założyłem, że wszystko jest gotowe. Jednak ten kod był nadal w onCreate (); eksperymentując z Thread.sleep () odkryłem, że układ nie jest tak naprawdę sfinalizowany, dopóki onCreate () nie skończy się do uruchomienia onResume (). W rzeczy samej, kod próbował uruchomić się zanim układ skończył się pozycjonować na ekranie. Dodając kod do OnClickListener (lub innego Listenera) uzyskano prawidłowe wartości, ponieważ można go było uruchomić tylko po zakończeniu układu.
Poniższy wiersz został zaproponowany jako edycja społeczności:
proszę użyć
onWindowfocuschanged(boolean hasFocus)
źródło
setContentView(R.layout.something)
, ale nie zostały wizualnie załadowane. Nie mają rozmiaru ani pozycji. Nie dzieje się tak, dopóki nie zakończy się pierwsze przejście układu, co dzieje się w pewnym momencie w przyszłości (zazwyczaj po onResume ()).Pierwszy sposób:
W Kotlin możemy stworzyć proste rozszerzenie do podglądu:
I po prostu uzyskaj współrzędne:
Drugi sposób:
Drugi sposób jest prostszy:
i po prostu uzyskaj absolutne X przez
view.absX()
i Y przezview.absY()
źródło
val location = IntArray(2).apply(::getLocationOnScreen)
Moja funkcja utils pozwala uzyskać lokalizację widoku, zwróci
Point
obiekt za pomocąx value
iy value
Za pomocą
źródło
Współrzędne widoku można uzyskać za pomocą
getLocationOnScreen()
lubgetLocationInWindow()
Później,
x
iy
powinno być w lewym górnym rogu widoku. Jeśli Twój układ główny jest mniejszy niż ekran (jak w oknie dialogowym), użyjgetLocationInWindow
będzie zależało od kontenera, a nie od całego ekranu.Rozwiązanie Java
Aby upewnić się, że widok miał szansę zaktualizować, uruchom zapytanie o lokalizację po obliczeniu nowego układu Widoku przy użyciu
view.post
:~~
Rozwiązanie Kotlin
Aby upewnić się, że widok miał szansę zaktualizować, uruchom zapytanie o lokalizację po obliczeniu nowego układu Widoku przy użyciu
view.post
:Polecam utworzenie funkcji rozszerzenia do obsługi tego:
A jeśli potrzebujesz niezawodności, dodaj także:
źródło
Użyj tego kodu, aby znaleźć dokładne cordinate X i Y:
Dodałem / odjąłem niektóre wartości, aby dostosować mój widok. Wykonaj te wiersze dopiero po zawyżeniu całego widoku.
źródło
Uzyskaj zarówno pozycję wyświetlania, jak i wymiar na ekranie
źródło
Oprócz powyższych odpowiedzi na pytanie, gdzie i kiedy należy zadzwonić
getLocationOnScreen
?We wszystkich informacjach związanych z dowolnym widokiem, który chcesz uzyskać, będzie on dostępny dopiero po ułożeniu widoku na ekranie. Możesz to łatwo zrobić, umieszczając w tym miejscu kod zależny od tworzenia widoku (view.post (Runnable)):
źródło