2010-02-08 9 views
306

Ich versuche, die absoluten Bildschirmpixelkoordinaten der oberen linken Ecke einer Ansicht zu erhalten. Alle Methoden, die ich finden kann, wie getLeft() und getRight() funktionieren jedoch nicht, da sie alle relativ zum übergeordneten Element der Ansicht zu sein scheinen, so dass mir 0. Was ist der richtige Weg, dies zu tun?So erhalten Sie die absoluten Koordinaten einer Ansicht

Wenn es hilft, ist dies für ein Spiel "das Bild in Ordnung bringen". Ich möchte, dass der Benutzer eine Box zeichnen kann, um mehrere Teile auszuwählen. Meine Annahme ist, dass der einfachste Weg das zu tun ist, getRawX() und-von der MotionEvent und vergleichen Sie dann diese Werte gegen die obere linke Ecke des Layouts, das die Stücke hält. Wenn ich die Größe der Teile kenne, kann ich bestimmen, wie viele Teile ausgewählt wurden. Ich weiß, dass ich getX() und getY() auf dem MotionEvent verwenden kann, aber da das eine relative Position zurückgibt, die das Bestimmen der ausgewählten Teile schwieriger macht. (Nicht unmöglich, ich weiß, aber es scheint unnötig kompliziert).

Edit: Dies ist der Code, den ich verwendet habe, um zu versuchen, die Größe des Container zu erhalten, wie eine der Fragen. 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()); 

Edit 2: Hier ist der Code, den ich habe versucht, mehrere der vorgeschlagenen Antworten folgen.

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 nach der Initialisierung hinzugefügt. Das Bild wurde in ein Array von ImageViews (das Array cells []) aufgeteilt, das in einem TableLayout enthalten ist. Zellen [0] ist die obere linke ImageView, und ich wählte Zellen [4] wie es irgendwo in der Mitte ist und sollte definitiv keine Koordinaten von (0,0) haben.

Der oben gezeigte Code gibt mir immer noch alle 0s in den Logs, was ich wirklich nicht verstehe, weil die verschiedenen Puzzleteile korrekt angezeigt werden. (Ich versuchte public int für tableLayoutCorners und Standard Sichtbarkeit, beide geben das gleiche Ergebnis.)

Ich weiß nicht, ob das signifikant ist, aber die ImageView s sind ursprünglich nicht eine Größe gegeben. Die Größe der ImageView s wird während der Initialisierung automatisch von der View bestimmt, wenn ich ihr ein Bild zur Anzeige gebe. Könnte dies dazu beitragen, dass ihre Werte 0 sind, obwohl der Logging-Code nach dem Eingeben eines Bildes und automatischem Ändern der Größe der Größe erfolgt? Um dem entgegenzuwirken, habe ich den Code tableLayout.requestLayout() wie oben gezeigt hinzugefügt, aber das hat nicht geholfen.

Antwort

506

Verwenden Sie View.getLocationOnScreen() und/oder getLocationInWindow().

+3

Nun, das ist die Art von Funktion I erwartet zu finden. Leider darf ich es nicht richtig gebrauchen. Ich weiß, dass es ein bekannter Fehler war, dass getLocationOnScreen eine Nullzeiger-Ausnahme in Android v1.5 (der Plattform, für die ich kodiere) gibt, aber das Testen in Version 2.1 funktionierte nicht besser. Beide Methoden gaben mir 0 für alles. Ich habe oben ein Code-Snippet eingefügt. –

+61

Sie können es nur aufrufen * AFTER * Layout ist passiert. Sie rufen die Methode auf, bevor die Ansichten auf dem Bildschirm positioniert werden. –

+4

Aha, du hast Recht, obwohl es nicht offensichtlich war, dass ich das tat. Vielen Dank! Für jeden, der neugierig auf mehr Details ist, habe ich eine Antwort hinzugefügt, die erklärt, was ich meine. –

52

Zuerst müssen Sie das localVisible Rechteck des

Für zB Ansichten:

Rect rectf = new Rect(); 

//For coordinates location relative to the parent 
anyView.getLocalVisibleRect(rectf); 

//For coordinates location relative to the screen/display 
anyView.getGlobalVisibleRect(rectf); 

Log.d("WIDTH  :", String.valueOf(rectf.width())); 
Log.d("HEIGHT  :", String.valueOf(rectf.height())); 
Log.d("left   :", String.valueOf(rectf.left)); 
Log.d("right  :", String.valueOf(rectf.right)); 
Log.d("top   :", String.valueOf(rectf.top)); 
Log.d("bottom  :", String.valueOf(rectf.bottom)); 

Hope this

+2

Das hätte auch funktionieren sollen ... Aber es gibt mir auch Werte von 0. Ich habe oben ein Code-Snippet eingefügt, wenn Sie dadurch herausfinden können, was ich falsch gemacht habe. Danke noch einmal. –

+1

Siehe meine anderen Kommentare; Ich rief das versehentlich an, bevor die Views fertig waren. Das funktioniert jetzt gut, danke. –

+0

@Naveen Murthy gibt Koordinaten zu bestimmten Ansicht, ich brauche Koordinaten der angeklickten Ansicht im Root-Layout .. – Aniket

15

Nach Romain Guy Kommentar helfen, hier ist, wie ich es behoben. Hoffentlich hilft es jedem anderen, der auch dieses Problem hatte.

Ich versuchte tatsächlich, die Positionen der Ansichten zu bekommen, bevor sie auf den Bildschirm gelegt worden waren, aber es war überhaupt nicht offensichtlich, dass das passierte. Diese Zeilen wurden platziert, nachdem der Initialisierungscode ausgeführt wurde, also nahm ich an, dass alles bereit war. Dieser Code war jedoch immer noch in onCreate(); indem Sie mit Thread experimentieren.sleep() Ich habe festgestellt, dass das Layout nicht wirklich abgeschlossen ist, bis onCreate() den ganzen Weg bis onResume() beendet wurde. In der Tat versuchte der Code zu laufen, bevor das Layout auf dem Bildschirm positioniert wurde. Durch Hinzufügen des Codes zu einem OnClickListener (oder einem anderen Listener) wurden die korrekten Werte erhalten, da er nur nach dem Ende des Layouts ausgelöst werden konnte.


Die Linie unten als Gemeinschaft bearbeiten vorgeschlagen wurde:

bitte für mich onWindowfocuschanged(boolean hasFocus)

+0

Also meinst du sagen setContentView (my_layout); wird nicht alle Ansichten platzieren. Alle Ansichten werden erst platziert, nachdem onCreate() beendet wurde. – Ashwin

+5

Nicht ganz. Alle Ansichten existieren nach 'setContentView (R.layout.etwas)', aber sie wurden nicht visuell geladen. Sie haben keine Größe oder Position. Das passiert erst, wenn der erste Layout-Durchlauf beendet ist, was irgendwann in der Zukunft passiert (normalerweise nach onResume()). –

35

verwenden hat immer gut ein globales Layout Hörer verwenden. Es hat den Vorteil, dass es in der Lage ist, Dinge neu zu messen, wenn das Layout geändert wird, z. Wenn etwas auf "View.GONE" eingestellt ist oder Kinderansichten hinzugefügt/entfernt werden.

public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 

    // inflate your main layout here (use RelativeLayout or whatever your root ViewGroup type is 
    LinearLayout mainLayout = (LinearLayout) this.getLayoutInflater().inflate(R.layout.main, null); 

    // set a global layout listener which will be called when the layout pass is completed and the view is drawn 
    mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(
     new ViewTreeObserver.OnGlobalLayoutListener() { 
      public void onGlobalLayout() { 
       //Remove the listener before proceeding 
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 
        mainLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
       } else { 
        mainLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
       } 

       // measure your views here 
      } 
     } 
    ); 

    setContentView(mainLayout); 
} 
+0

Vergessen Sie nicht, den OnGlobalLayoutListener innerhalb von (am Ende von) onGlobalLayout() {...} zu entfernen. Überprüfen Sie auch, ob das, was passiert ist! = 0; der Listener kann zweimal aufgerufen werden, einmal mit einem Wert von w = 0/h = 0, das zweite Mal mit den tatsächlichen, korrekten Werten. – MacD

+0

Dieser Weg, um das Hauptlayout aufzublasen und 'setContentView()' zu benutzen, verursachte ein Problem in einer speziellen 'Aktivität' in meiner App! Das war eine Dialogaktivität ('windowFrame: @null, windowActionBar: false, windowIsFloating: true, windowNoTitle: true'). Sein Hauptlayout (ein 'LinearLayout') hat kein direktes Kind mit festgelegter' layout_width' (alle waren 'match_parent' oder' wrap_content'). –

0

Verwendung Dieser Code genau X und Y cordinates zu finden:

int[] array = new int[2]; 
ViewForWhichLocationIsToBeFound.getLocationOnScreen(array); 
if (AppConstants.DEBUG) 
    Log.d(AppConstants.TAG, "array X = " + array[0] + ", Y = " + array[1]); 
ViewWhichToBeMovedOnFoundLocation.setTranslationX(array[0] + 21); 
ViewWhichToBeMovedOnFoundLocation.setTranslationY(array[1] - 165); 

Ich habe hinzugefügt/einige Werte subtrahiert meine Ansicht anzupassen. Bitte machen Sie diese Zeilen erst, nachdem die ganze Ansicht aufgebläht wurde.

47

Die angenommene Antwort hat nicht wirklich gesagt, wie man den Standort bekommt, also hier ist ein wenig mehr Detail. 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.

int[] location = new int[2]; 
myView.getLocationOnScreen(location); 
int x = location[0]; 
int y = location[1]; 

Hinweise

  • Ersetzen getLocationOnScreen mit getLocationInWindow sollten die gleichen Ergebnisse in den meisten Fällen geben (siehe this answer).
  • Sie erhalten (0,0), wenn Sie diese Methode in onCreate aufrufen, weil die Ansicht noch nicht ausgelegt wurde. Sie können eine ViewTreeObserver verwenden, um zu hören, wenn das Layout fertig ist und Sie die gemessenen Koordinaten erhalten können. (Siehe this answer.)
2

Meine utils-Funktion für get Ansicht Lage, es wird ein Point Objekt zurück mit x value und y value

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

Mit

Point viewALocation = getLocationOnScreen(viewA); 
Verwandte Themen