Ich versuche, die absoluten Bildschirmpixelkoordinaten der oberen linken Ecke einer Ansicht zu ermitteln. Alle Methoden, die ich finden kann, funktionieren jedoch nicht getLeft()
und getRight()
funktionieren nicht, da sie alle relativ zum übergeordneten Element der Ansicht zu sein scheinen 0
. Was ist der richtige Weg, um dies zu tun?
Wenn es hilft, ist dies für ein Spiel, bei dem das Bild wieder in Ordnung gebracht wird. Ich möchte, dass der Benutzer eine Box zeichnen kann, um mehrere Teile auszuwählen. Meine Vermutung ist , dass der einfachste Weg , dies zu tun ist , um getRawX()
und getRawY()
aus der MotionEvent
und vergleichen diese Werte dann gegen die linke obere Ecke des Layouts , die Stücke zu halten. Wenn ich die Größe der Stücke kenne, kann ich dann bestimmen, wie viele Stücke ausgewählt wurden. Mir ist klar, dass ich getX()
und getY()
auf dem verwenden kann MotionEvent
, aber da dies eine relative Position zurückgibt, die es schwieriger macht, zu bestimmen, welche Stücke ausgewählt wurden. (Nicht unmöglich, ich weiß, aber es scheint unnötig kompliziert).
Bearbeiten: Dies ist der Code, mit dem ich versucht habe, die Größe des Vorratsbehälters gemäß einer der Fragen zu ermitteln. TableLayout
ist der Tisch, der alle Puzzleteile enthält.
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
Log.d(LOG_TAG, "Values " + tableLayout.getTop() + tableLayout.getLeft());
Bearbeiten 2: Hier ist der Code, den ich ausprobiert habe, und folge den vorgeschlagenen Antworten.
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]);
Dieser Code wurde hinzugefügt, nachdem die Initialisierung abgeschlossen ist. Das Bild wurde in ein Array von ImageViews (das Zellen [] -Array) unterteilt, das in a enthalten ist TableLayout
. Zellen [0] sind oben links ImageView
, und ich habe Zellen [4] ausgewählt, da sie irgendwo in der Mitte liegen und definitiv keine Koordinaten von (0,0) haben sollten.
Der oben gezeigte Code gibt mir immer noch alle Nullen in den Protokollen, was ich wirklich nicht verstehe, weil die verschiedenen Puzzleteile korrekt angezeigt werden. (Ich habe versucht, public int für tableLayoutCorners und die Standardsichtbarkeit zu verwenden, wobei beide das gleiche Ergebnis liefern.)
Ich weiß nicht, ob dies von Bedeutung ist, aber die ImageView
s haben ursprünglich keine Größe. Die Größe des ImageView
s wird während der Initialisierung automatisch von der Ansicht bestimmt, wenn ich ihm ein Bild zur Anzeige gebe. Könnte dies dazu beitragen, dass ihre Werte 0 sind, obwohl dieser Protokollierungscode steht, nachdem sie ein Bild erhalten und ihre Größe automatisch geändert haben? Um dem möglicherweise entgegenzuwirken, habe ich den Code tableLayout.requestLayout()
wie oben gezeigt hinzugefügt , aber das hat nicht geholfen.
quelle
In der akzeptierten Antwort wurde nicht angegeben, wie der Standort ermittelt werden soll. Hier finden Sie einige Details. Sie übergeben ein
int
Array der Länge 2 und die Werte werden durch die Koordinaten der Ansicht (x, y) (der oberen linken Ecke) ersetzt.Anmerkungen
getLocationOnScreen
durchgetLocationInWindow
sollte in den meisten Fällen zu denselben Ergebnissen führen (siehe diese Antwort ). Wenn Sie sich jedoch in einem kleineren Fenster wie einem Dialogfeld oder einer benutzerdefinierten Tastatur befinden, müssen Sie auswählen, welches Fenster Ihren Anforderungen besser entspricht.(0,0)
wenn Sie diese Methode aufrufen,onCreate
da die Ansicht noch nicht angelegt wurde. Mit a können SieViewTreeObserver
abhören, wann das Layout fertig ist, und die gemessenen Koordinaten abrufen. (Siehe diese Antwort .)quelle
Zuerst müssen Sie das localVisible-Rechteck der Ansicht abrufen
Zum Beispiel:
Hoffe das wird helfen
quelle
getGlobalVisibleRect()
für absolute Koordinaten.Die Verwendung eines globalen Layout-Listeners hat bei mir immer gut funktioniert. Es hat den Vorteil, dass Dinge neu gemessen werden können, wenn das Layout geändert wird, z. B. wenn etwas auf View.GONE gesetzt ist oder untergeordnete Ansichten hinzugefügt / entfernt werden.
quelle
setContentView()
verursachte ein Problem in einem SpecialActivity
in meiner App! Das war eine Dialogaktivität (windowFrame:@null, windowActionBar:false, windowIsFloating:true, windowNoTitle:true
). Sein Hauptlayout (aLinearLayout
) hat kein direktes Kind mit bestimmtlayout_width
(Alle warenmatch_parent
oderwrap_content
).Nach dem Kommentar von Romain Guy habe ich Folgendes behoben. Hoffentlich hilft es allen anderen, die dieses Problem ebenfalls hatten.
Ich habe zwar versucht, die Positionen der Ansichten zu ermitteln, bevor sie auf dem Bildschirm angezeigt wurden, aber es war überhaupt nicht offensichtlich, dass dies geschah. Diese Zeilen wurden platziert, nachdem der Initilisierungscode ausgeführt wurde, sodass ich davon ausging, dass alles bereit war. Dieser Code befand sich jedoch noch in onCreate (). Beim Experimentieren mit Thread.sleep () stellte ich fest, dass das Layout erst fertiggestellt wird, nachdem onCreate () bis zur Ausführung von onResume () abgeschlossen wurde. Der Code versuchte also tatsächlich auszuführen, bevor das Layout nicht mehr auf dem Bildschirm positioniert war. Durch Hinzufügen des Codes zu einem OnClickListener (oder einem anderen Listener) wurden die korrekten Werte erhalten, da er erst nach Abschluss des Layouts ausgelöst werden konnte.
Die folgende Zeile wurde als Community-Bearbeitung vorgeschlagen:
benutzen Sie bitte
onWindowfocuschanged(boolean hasFocus)
quelle
setContentView(R.layout.something)
, wurden jedoch nicht visuell geladen. Sie haben keine Größe oder Position. Dies geschieht erst, wenn der erste Layoutdurchlauf abgeschlossen ist, was zu einem späteren Zeitpunkt geschieht (in der Regel nach onResume ()).Erster Weg:
In Kotlin können wir eine einfache Erweiterung für die Ansicht erstellen:
Und einfach Koordinaten bekommen:
Zweiter Weg:
Der zweite Weg ist einfacher:
und einfach das absolute X von
view.absX()
und Y von erhaltenview.absY()
quelle
val location = IntArray(2).apply(::getLocationOnScreen)
Meine Utils-Funktion zum Abrufen des Ansichtsorts gibt ein
Point
Objekt mitx value
und zurücky value
Verwenden von
quelle
Sie können die Koordinaten einer Ansicht mit
getLocationOnScreen()
oder abrufengetLocationInWindow()
Danach
x
undy
sollte die obere linke Ecke der Ansicht sein. Wenn Ihr Root-Layout kleiner als der Bildschirm ist (wie in einem Dialogfeld), beziehtgetLocationInWindow
sich die Verwendung auf den Container und nicht auf den gesamten Bildschirm.Java-Lösung
Um sicherzustellen, dass die Ansicht aktualisiert werden konnte, führen Sie Ihre Standortanforderung aus, nachdem das neue Layout der Ansicht mithilfe von Folgendem berechnet wurde
view.post
:~~
Kotlin-Lösung
Um sicherzustellen, dass die Ansicht aktualisiert werden konnte, führen Sie Ihre Standortanforderung aus, nachdem das neue Layout der Ansicht mithilfe von Folgendem berechnet wurde
view.post
:Ich empfehle, eine Erweiterungsfunktion zu erstellen, um dies zu handhaben:
Und wenn Sie Zuverlässigkeit benötigen, fügen Sie hinzu:
quelle
Verwenden Sie diesen Code, um genaue X- und Y-Koordinaten zu finden:
Ich habe einige Werte addiert / subtrahiert, um meine Ansicht anzupassen. Bitte machen Sie diese Zeilen erst, nachdem die gesamte Ansicht aufgeblasen wurde.
quelle
Holen Sie sich sowohl Ansichtsposition als auch Bemaßung auf dem Bildschirm
quelle
Nur zusätzlich zu den obigen Antworten, für die Frage, wo und wann Sie anrufen sollten
getLocationOnScreen
?Informationen zu einer Ansicht, die Sie abrufen möchten, sind erst verfügbar, nachdem die Ansicht auf dem Bildschirm angezeigt wurde. Sie können dies einfach tun, indem Sie Ihren Code, der von der Erstellung der Ansicht abhängt, in diese (view.post (Runnable)) einfügen:
quelle