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.

700voto

Romain Guy Punkte 96489

3 Stimmen

Das ist die Art von Funktion, die ich erwartet habe. Leider muss ich es nicht richtig verwenden. Ich weiß, dass es ein bekannter Fehler war, dass getLocationOnScreen in Android v1.5 (die Plattform, für die ich programmiere) eine Null-Pointer-Ausnahme erzeugt, aber das Testen in v2.1 hat nicht besser funktioniert. Beide Methoden gaben mir 0s für alles. Ich habe einen Code-Schnipsel oben enthalten.

83 Stimmen

Sie können es nur aufrufen NACH Layout geschehen ist. Sie rufen die Methode auf, bevor die Ansichten auf dem Bildschirm positioniert sind.

5 Stimmen

Aha, du hast recht, obwohl es nicht offensichtlich war, dass ich das tat. Danke! Für alle, die neugierig auf mehr Details sind, habe ich eine Antwort hinzugefügt, die erklärt, was ich meine.

190voto

Suragch Punkte 420096

In der akzeptierten Antwort wurde nicht gesagt, wie man den Standort ermittelt, daher hier ein paar weitere Details. Sie übergeben eine int Array der Länge 2 und die Werte werden durch die (x, y)-Koordinaten der Ansicht (der oberen linken Ecke) ersetzt.

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

Notas

  • Ersetzen von getLocationOnScreen con getLocationInWindow sollte in den meisten Fällen zu den gleichen Ergebnissen führen (siehe diese Antwort ). Wenn Sie sich jedoch in einem kleineren Fenster wie einem Dialog oder einer benutzerdefinierten Tastatur befinden, müssen Sie sich entscheiden, welche Option Ihren Bedürfnissen besser entspricht.
  • Sie erhalten (0,0) wenn Sie diese Methode in onCreate weil die Ansicht noch nicht festgelegt wurde. Sie können eine ViewTreeObserver um zu hören, wann das Layout fertig ist und Sie die gemessenen Koordinaten erhalten können. (Siehe diese Antwort .)

0 Stimmen

Oder überschreiben Sie die Methode onWindowFocusChanged und verwenden Sie sie dort

114voto

Naveen Murthy Punkte 3581

Zuerst müssen Sie das localVisible-Rechteck der Ansicht ermitteln

Zum Beispiel:

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));

Ich hoffe, das hilft

4 Stimmen

Das hätte auch funktionieren müssen... Aber es gibt mir auch Werte von 0. Ich habe einen Code-Schnipsel oben, wenn das hilft Ihnen herauszufinden, was ich falsch gemacht habe. Nochmals vielen Dank.

1 Stimmen

Siehe meine anderen Kommentare; ich rief dies versehentlich auf, bevor die Ansichten fertig waren, sich anzulegen. Dies funktioniert jetzt gut, danke.

0 Stimmen

@Naveen Murthy es gibt Koordinaten zu bestimmten Ansicht, ich brauche Koordinaten der angeklickten Ansicht in Root-Layout

51voto

Simon Punkte 14189

Die Verwendung eines globalen Layout-Listeners hat bei mir immer gut funktioniert. Es hat den Vorteil, dass es in der Lage ist, Dinge neu zu messen, wenn das Layout geändert wird, z. B. wenn etwas auf View.GONE gesetzt wird oder untergeordnete Ansichten 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 Stimmen

Vergessen Sie nicht, den OnGlobalLayoutListener innerhalb (am Ende) des onGlobalLayout(){...} zu entfernen. Prüfen Sie außerdem, nur um sicher zu gehen, ob what' \s übergeben != 0; der Hörer kann zweimal aufgerufen werden, einmal mit einem Wert von w=0/h=0, das zweite Mal mit den tatsächlichen, korrekten Werten.

0 Stimmen

Auf diese Weise können Sie das Hauptlayout aufblasen und dann mit setContentView() ein Problem in einem speziellen Activity 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 bestimmten layout_width (Alle von ihnen waren match_parent ou wrap_content ).

28voto

Amir Hossein Ghasemi Punkte 15079

Erster Weg:

En Kotlin können wir eine einfache Erweiterung für view erstellen:

fun View.getLocationOnScreen(): Point
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return Point(location[0],location[1])
}

Und holen Sie sich einfach Koordinaten:

val location = yourView.getLocationOnScreen()
val absX = location.x
val absY = location.y

Zweiter Weg:

Der zweite Weg ist einfacher:

fun View.absX(): Int
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return location[0]
}

fun View.absY(): Int
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return location[1]
}

und erhalten Sie einfach das absolute X durch view.absX() und Y durch view.absY()

8 Stimmen

Eine kürzere Version für Ihre 1. Probe: val location = IntArray(2).apply(::getLocationOnScreen)

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