web-dev-qa-db-de.com

getLocationOnScreen () vs getLocationInWindow ()

Was ist der Unterschied zwischen Bildschirm und Ansicht im Kontext dieser beiden Methoden?

Ich habe eine Schaltfläche und möchte die x-Koordinate des Mittelpunkts ermitteln.

Ich denke das wäre genug:

public int getButtonXPosition() {
    return (button.getLeft()+button.getRight())/2;
}

aber dann, welchen Unterschied würde es machen, wenn ich benutzt hätte

getLocationOnScreen() oder getLocationInWindow()?

(Dazu kommt natürlich die Hälfte der Breite des Buttons)

63
Elad Benda

Ich denke nicht, dass diese Antwort richtig ist. Wenn ich ein neues Projekt erstelle und nur die MainActivity bearbeite, fügen Sie das folgende Snippet hinzu:

public boolean dispatchTouchEvent(MotionEvent ev) {
    View contentsView = findViewById(Android.R.id.content);

    int test1[] = new int[2];
    contentsView.getLocationInWindow(test1);

    int test2[] = new int[2];
    contentsView.getLocationOnScreen(test2);

    System.out.println(test1[1] + " " + test2[1]);

    return super.dispatchTouchEvent(ev);
}

Ich werde auf die Konsole gedruckt sehen 108 108. Hierfür wird ein Nexus 7 verwendet, auf dem 4.3 ausgeführt wird. Ich habe ähnliche Ergebnisse mit Emulatoren, auf denen Android Versionen bis 2.2.

Normale Aktivitätsfenster haben FILL_PARENTxFILL_PARENT als WindowManager.LayoutParams, was dazu führt, dass sie auf die Größe des gesamten Bildschirms ausgelegt werden. Das Fenster ist unter der Statusleiste und anderen Dekorationen angeordnet (in Bezug auf die Z-Reihenfolge, nicht die Y-Koordinaten). Ich glaube, ein genaueres Diagramm wäre also:

|--phone screen-----activity window---| 
|--------status bar-------------------| 
|                                     | 
|                                     | 
|-------------------------------------| 

Wenn Sie die Quelle dieser beiden Methoden durchgehen, werden Sie feststellen, dass getLocationInWindow die Ansichtshierarchie Ihrer Ansicht bis zum RootViewImpl durchläuft, die Ansichtskoordinaten summiert und übergeordnete Bildlaufversätze subtrahiert. In dem oben beschriebenen Fall ruft ViewRootImpl die Höhe der Statusleiste aus der WindowSession ab und leitet sie über fitSystemWindows an das ActionBarOverlayLayout weiter, das diesen Wert zur Höhe der Aktionsleiste hinzufügt. ActionBarOverlayLayout verwendet dann diesen summierten Wert und wendet ihn als Rand auf seine Inhaltsansicht an, die das übergeordnete Element Ihres Layouts ist.

Ihr Inhalt ist also niedriger als die Statusleiste angeordnet, nicht weil das Fenster an einer niedrigeren y-Koordinate beginnt als die Statusleiste, sondern weil ein Rand auf die Inhaltsansicht Ihrer Aktivität angewendet wird.

Wenn Sie in die getLocationOnScreen -Quelle blicken, werden Sie sehen, dass sie nur getLocationInWindow aufruft und dann die linken und oberen Koordinaten des Fensters hinzufügt (die auch von ViewRootImpl an View übergeben werden, um sie von der abzurufen WindowSession). Im Normalfall sind beide Werte Null. Es gibt Situationen, in denen diese Werte möglicherweise nicht Null sind, z. B. ein Dialogfeld, das in der Mitte des Bildschirms angezeigt wird.


Um es zusammenzufassen: Das Fenster einer normalen Aktivität füllt den gesamten Bildschirm aus, sogar den Raum unter der Statusleiste und den Dekorationen. Die beiden fraglichen Methoden geben die gleichen x- und y-Koordinaten zurück. Nur in besonderen Fällen, z. B. in Dialogen, in denen das Fenster tatsächlich versetzt ist, unterscheiden sich diese beiden Werte.

110
groucho

getLocationOnScreen () ermittelt den Standort basierend auf Telefonbildschirm.

getLocationInWindow () ermittelt den Standort anhand des Aktivitätsfensters.

Für die normale Aktivität (keine Vollbildaktivität) ist die Beziehung zum Telefonbildschirm und zum Aktivitätsfenster wie folgt:

| --Telefonbildschirm ------------------
| ----------- (Statusleiste
------------------
| |
| ------------------------------------------- |
| ----------- (Aktivitätsfenster
------ ------- |
| |
| |
| |
| |
| |
| |
| ------------------------------------------- |

Für die x-Koordinate ist der Wert beider Methoden normalerweise gleich.

Für die y-Koordinate haben die Werte einen Unterschied für die Höhe der Statusleiste

24
Ivan

Die derzeit akzeptierte Antwort ist ein wenig wortreich. Hier ist eine kürzere.

getLocationOnScreen() und getLocationInWindow() geben normalerweise die gleichen Werte zurück. Dies liegt daran, dass das Fenster normalerweise dieselbe Größe wie der Bildschirm hat. Manchmal ist das Fenster jedoch kleiner als der Bildschirm. Zum Beispiel in einer Dialog oder einer benutzerdefinierten Systemtastatur.

Wenn Sie also wissen, dass die gewünschten Koordinaten immer relativ zum Bildschirm sind (wie bei einer normalen Aktivität), können Sie getLocationOnScreen() verwenden. Befindet sich Ihre Ansicht jedoch in einem Fenster, das möglicherweise kleiner als der Bildschirm ist (wie in einem Dialogfeld oder einer benutzerdefinierten Tastatur), verwenden Sie getLocationInWindow().

Verwandte

4
Suragch