456 Stimmen

Wie man die absoluten Koordinaten einer Ansicht erhält

Ich versuche, die absoluten Bildschirm-Pixelkoordinaten der linken oberen Ecke einer Ansicht zu ermitteln. Allerdings sind alle Methoden, die ich finden kann, wie zum Beispiel getLeft() y getRight() funktionieren nicht, da sie alle relativ zum Elternteil der Ansicht zu sein scheinen, so dass ich 0 . Wie geht man dabei richtig vor?

Wenn es hilft, ist dies ein Spiel, bei dem es darum geht, das Bild wieder in Ordnung zu bringen. Ich möchte, dass der Benutzer ein Feld zeichnen kann, um mehrere Teile auszuwählen. Ich gehe davon aus, dass dies am einfachsten möglich ist, wenn man getRawX() y getRawY() von der MotionEvent und vergleichen Sie diese Werte dann mit der linken oberen Ecke des Layouts, in dem sich die Teile befinden. Wenn ich die Größe der Teile kenne, kann ich feststellen, wie viele Teile ausgewählt wurden. Ich weiß, dass ich Folgendes verwenden kann getX() y getY() über die MotionEvent Da dies jedoch eine relative Position ergibt, ist es schwieriger zu bestimmen, welche Stücke ausgewählt wurden. (Nicht unmöglich, ich weiß, aber es scheint unnötig kompliziert).

Edit: Dies ist der Code, mit dem ich versucht habe, die Größe des Containers zu ermitteln, wie in einer der Fragen beschrieben. TableLayout ist der Tisch, auf dem alle Puzzleteile liegen.

TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
Log.d(LOG_TAG, "Values " + tableLayout.getTop() + tableLayout.getLeft());

Edit 2: Hier ist der Code, den ich versucht habe, nach mehr der 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 cell[]-Array) aufgeteilt, das in einer TableLayout . Cells[0] ist die obere linke Seite ImageView und ich habe cells[4] ausgewählt, da es irgendwo in der Mitte liegt und auf keinen Fall Koordinaten von (0,0) haben sollte.

Mit dem oben gezeigten Code erhalte ich immer noch alle 0en in den Protokollen, was ich wirklich nicht verstehe, da die verschiedenen Puzzleteile korrekt angezeigt werden. (Ich habe public int für tableLayoutCorners und default visibility ausprobiert, was beides das gleiche Ergebnis liefert).

Ich weiß nicht, ob dies von Bedeutung ist, aber die ImageView s sind ursprünglich nicht mit einer Größe versehen. Die Größe der ImageView s wird während der Initialisierung automatisch von der Ansicht bestimmt, wenn ich ihr ein Bild zur Anzeige gebe. Könnte dies dazu beitragen, dass ihre Werte 0 sind, auch wenn der Protokollierungscode nach der Übergabe eines Bildes und der automatischen Größenänderung erfolgt? Um dem möglicherweise entgegenzuwirken, habe ich folgenden Code hinzugefügt tableLayout.requestLayout() wie oben gezeigt, aber das hat nicht geholfen.

19voto

Steve Haley Punkte 54674

Dem Kommentar von Romain Guy folgend, habe ich das Problem folgendermaßen gelöst. Hoffentlich hilft es allen anderen, die dieses Problem auch hatten.

Ich habe in der Tat 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 eingefügt, nachdem der Initialisierungscode ausgeführt wurde, also nahm ich an, dass alles fertig war. Dieser Code befand sich jedoch noch in onCreate(); durch Experimente mit Thread.sleep() fand ich heraus, dass das Layout erst nach der Ausführung von onCreate() bis hin zu onResume() fertiggestellt wird. Der Code versuchte also tatsächlich, ausgeführt zu werden, bevor das Layout 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 von der Gemeinschaft vorgeschlagen:

bitte benutzen onWindowfocuschanged(boolean hasFocus)

0 Stimmen

Sie wollen also sagen, dass setContentView(my_layout); nicht alle Ansichten platzieren wird. Alle Ansichten werden erst platziert, nachdem onCreate() beendet ist?

5 Stimmen

Nicht ganz. Alle Ansichten "existieren" nach setContentView(R.layout.something) aber sie wurden nicht visuell aufgeladen. Sie haben weder eine Größe noch eine Position. Das geschieht erst, wenn der erste Layout-Durchgang abgeschlossen ist, was irgendwann in der Zukunft geschieht (im Allgemeinen nach onResume()).

17voto

Gibolt Punkte 32347

Sie können die Koordinaten einer Ansicht mit getLocationOnScreen() o getLocationInWindow()

Danach, x y y sollte die linke obere Ecke der Ansicht sein. Wenn Ihr Root-Layout kleiner als der Bildschirm ist (wie in einem Dialog), sollten Sie getLocationInWindow bezieht sich auf den Container und nicht auf den gesamten Bildschirm.

Java-Lösung

int[] point = new int[2];
view.getLocationOnScreen(point); // or getLocationInWindow(point)
int x = point[0];
int y = point[1];

Wenn der Wert immer 0 ist, ändern Sie wahrscheinlich die Ansicht unmittelbar vor der Abfrage der Position.

Um sicherzustellen, dass die Ansicht die Möglichkeit hatte, sich zu aktualisieren, führen Sie Ihre Standortabfrage aus, nachdem das neue Layout der Ansicht berechnet wurde, indem Sie view.post :

view.post(() -> {
    // Values should no longer be 0
    int[] point = new int[2];
    view.getLocationOnScreen(point); // or getLocationInWindow(point)
    int x = point[0];
    int y = point[1];
});

~~

Kotlin-Lösung

val point = IntArray(2)
view.getLocationOnScreen(point) // or getLocationInWindow(point)
val (x, y) = point

Wenn der Wert immer 0 ist, ändern Sie wahrscheinlich die Ansicht unmittelbar vor der Abfrage der Position.

Um sicherzustellen, dass die Ansicht die Möglichkeit hatte, sich zu aktualisieren, führen Sie Ihre Standortabfrage aus, nachdem das neue Layout der Ansicht berechnet wurde, indem Sie view.post :

view.post {
    // Values should no longer be 0
    val point = IntArray(2)
    view.getLocationOnScreen(point) // or getLocationInWindow(point)
    val (x, y) = point
}

Ich empfehle die Erstellung einer Erweiterungsfunktion für diese Aufgabe:

// To use, call:
val (x, y) = view.screenLocation

val View.screenLocation get(): IntArray {
    val point = IntArray(2)
    getLocationOnScreen(point)
    return point
}

Und wenn Sie Zuverlässigkeit benötigen, fügen Sie auch hinzu:

view.screenLocationSafe { x, y -> Log.d("", "Use $x and $y here") }

fun View.screenLocationSafe(callback: (Int, Int) -> Unit) {
    post {
        val (x, y) = screenLocation
        callback(x, y)
    }
}

13voto

Suraj Vaishnav Punkte 6847

Ergänzend zu den oben genannten Antworten auf die Frage, wo und wann Sie anrufen sollten getLocationOnScreen ?

Für alle Informationen, die sich auf den view ist erst dann verfügbar, wenn die Ansicht auf dem Bildschirm erstellt wurde. Um also die Position zu erhalten, setzen Sie Ihren Code in view.post(Runnable) die aufgerufen wird nach view ist so angelegt:

view.post(new Runnable() {
            @Override
            public void run() {

               // This code will run when view created and rendered on screen

               // So as the answer to this question, you can put the code here
               int[] location = new int[2];
               myView.getLocationOnScreen(location);
               int x = location[0];
               int y = location[1];
            }
        });

6voto

Linh Punkte 49889

Meine Utilitys-Funktion für die Abfrage der Position der Ansicht, gibt eine Point Objekt mit x value y y value

public static Point getLocationOnScreen(View view){
    int[] location = new int[2];
    view.getLocationOnScreen(location);
    return new Point(location[0], location[1]);
}

Verwendung von

Point viewALocation = getLocationOnScreen(viewA);

0voto

Hitesh Sahu Punkte 37527

Ansichtsposition und Abmessungen auf dem Bildschirm anzeigen

val viewTreeObserver: ViewTreeObserver = videoView.viewTreeObserver;

    if (viewTreeObserver.isAlive) {
        viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                //Remove Listener
                videoView.viewTreeObserver.removeOnGlobalLayoutListener(this);

                //View Dimentions
                viewWidth = videoView.width;
                viewHeight = videoView.height;

                //View Location
                val point = IntArray(2)
                videoView.post {
                    videoView.getLocationOnScreen(point) // or getLocationInWindow(point)
                    viewPositionX = point[0]
                    viewPositionY = point[1]
                }

            }
        });
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X