Wie kann ich die Ansichtsposition in Android dynamisch einstellen?

102

Wie kann ich die Position der Ansicht durch Code ändern? Als würde man seine X-, Y-Position ändern. Ist es möglich?

Arun Badole
quelle

Antworten:

117

Für alles unter Honeycomb (API Level 11) müssen Sie verwenden setLayoutParams(...).

Wenn Sie Ihre Unterstützung für Honeycomb begrenzen und bis Sie verwenden können , die setX(...), setY(...), setLeft(...), setTop(...), usw.

Verderblicher Dave
quelle
40
aus den Dokumenten von setTop () developer.android.com/reference/android/view/… : sets the top position of this view relative to its parent. This method is meant to be called by the layout system and should not generally be called otherwise, because the property may be changed at any time by the layout.- vielleicht ist das keine so gute Idee;)
katzenhut
47

Ja, Sie können die Ansichtsposition in Android dynamisch festlegen. Ebenso haben Sie ein ImageViewIn LinearLayoutIhrer XML-Datei. So können Sie die Position durch LayoutParamsfestlegen. Achten Sie jedoch darauf, dass Sie LayoutParamsentsprechend dem in Ihrer XML-Datei aufgenommenen LayoutParamsLayout nehmen. Je nach Layout gibt es unterschiedliche Einstellungen .

Hier ist der Code zum Einstellen:

    LayoutParams layoutParams=new LayoutParams(int width, int height);
    layoutParams.setMargins(int left, int top, int right, int bottom);
    imageView.setLayoutParams(layoutParams);

Ich hoffe, es wird Ihnen hilfreich sein, die Position festzulegen.

AkashG
quelle
15
Beachten Sie auch, dass Sie android.widget.LinearLayout.LayoutParams importieren müssen. weil die Standardeinstellung die LayoutParams von ViewGroup ist
David T.
Dies scheint unter Android 8+ nicht zu funktionieren. Haben Sie ein ähnliches Problem gehabt?
MyFlashLab
Jede Idee, warum die Andriod-Designer sich so viel Mühe geben, um die Programmierer davon abzuhalten, X, Y zum Positionieren von Dingen zu verwenden. Schließlich muss alles so gezeichnet werden. Dies deutet darauf hin, dass Android von Personen entwickelt wird, die nicht codieren können.
Paul McCarthy
33

Es gibt bereits verschiedene gültige Antworten, aber keine scheint richtig vorzuschlagen, welche Methode (n) in welchem ​​Fall verwendet werden soll (sind), mit Ausnahme der entsprechenden Einschränkungen auf API-Ebene:

  • Wenn Sie auf einen Layoutzyklus warten können und die übergeordnete Ansichtsgruppe MarginLayoutParams(oder eine Unterklasse) unterstützt, setzen Sie marginLeft/ marginTopentsprechend.

  • Wenn Sie die Position sofort und dauerhaft ändern müssen (z. B. für einen PopupMenu-Anker), rufen Sie zusätzlich layout(l, t, r, b)mit denselben Koordinaten auf. Dies setzt voraus, was das Layoutsystem später bestätigt.

  • Verwenden Sie für sofortige (vorübergehende) Änderungen (z. B. Animationen) stattdessen setX()/ setY(). In Fällen, in denen die übergeordnete Größe nicht von WRAP_CHILDREN abhängt, ist es möglicherweise in Ordnung, setX()/ setY()ausschließlich zu verwenden.

  • Verwenden Sie niemalssetLeft() / setRight()/ setBottom()/ setTop(), siehe unten.

Hintergrund : Die Felder mLeft/ mTop/ mBottom/ mRightwerden von den entsprechenden LayoutParams in layout () ausgefüllt. Das Layout wird vom Android-Ansichtslayoutsystem implizit und asynchron aufgerufen. Daher MarginLayoutParamsscheint das Einstellen von die sicherste und sauberste Möglichkeit zu sein, die Position dauerhaft einzustellen. In einigen Fällen kann die asynchrone Layoutverzögerung jedoch ein Problem darstellen, z. B. wenn Sie eine Ansicht zum Rendern eines Cursors verwenden. Sie soll neu positioniert werden und gleichzeitig als PopupMenu-Anker dienen. In diesem Fall hat das Anrufen layout()für mich gut funktioniert.

Die Probleme mit setLeft()und setTop()sind:

  • Es reicht nicht aus, sie alleine anzurufen - Sie müssen auch anrufen setRight()und setBottom()vermeiden, dass die Ansicht gedehnt oder verkleinert wird.

  • Die Implementierung dieser Methoden sieht relativ komplex aus (= einige Arbeiten ausführen, um die durch jede von ihnen verursachten Änderungen der Ansichtsgröße zu berücksichtigen)

  • Sie scheinen seltsame Probleme mit Eingabefeldern zu verursachen: Die weiche numerische EditText-Tastatur lässt manchmal keine Ziffern zu

setX()und setY()arbeiten außerhalb des Layoutsystems, und die entsprechenden Werte werden als zusätzlicher Versatz zu den vom Layoutsystem festgelegten Werten für links / oben / unten / rechts behandelt, wodurch die Ansicht entsprechend verschoben wird. Sie scheinen für Animationen hinzugefügt worden zu sein (wo ein sofortiger Effekt erforderlich ist, ohne einen Layoutzyklus zu durchlaufen).

Stefan Haustein
quelle
Hallo Stefan. Könnten Sie einige Bücher oder Artikel beraten, in denen ich verstehen kann, wie das Android-Layout-System funktioniert. Ich verstehe diese Abfolge von layout () onMeasure () onDraw () -Aufrufen, möchte aber mehr Details darüber erfahren. Vielen Dank im Voraus
Sergey Brazhnik
Leider kann ich nicht - die beste und definitivste Referenz scheint der eigentliche Android-Quellcode O zu sein :)
Stefan Haustein
Ich benutze setY, um die Ansicht zu ändern. Wird sie im nächsten Layoutzyklus geändert, nicht sofort?
Signal
Wie haben Sie das festgestellt?
Stefan Haustein
Es ist erwähnenswert, dass das eingestellt werden marginLeftkann, indem man setLayoutParamsmit einem verwendet, new FrameLayout.LayoutParams(width, height)auf dem man denmarginLeft
lucidbrot
18

Es gibt eine Bibliothek namens NineOldAndroids , mit der Sie die Honeycomb-Animationsbibliothek bis zur ersten Version verwenden können.

Dies bedeutet, dass Sie left, right, translationX / Y mit einer etwas anderen Schnittstelle definieren können.

So funktioniert es:

ViewHelper.setTranslationX(view, 50f);

Sie verwenden einfach die statischen Methoden aus der ViewHelper-Klasse, übergeben die Ansicht und den Wert, auf den Sie sie festlegen möchten.

Ben
quelle
16

Ich würde empfehlen, setTranslationXund zu verwenden setTranslationY. Ich fange gerade erst selbst damit an, aber dies scheint die sicherste und bevorzugte Art zu sein, eine Ansicht zu verschieben. Ich denke, es hängt sehr davon ab, was genau Sie versuchen, aber das funktioniert gut für mich für 2D-Animationen.

brianmearns
quelle
13

Sie können versuchen, die folgenden Methoden zu verwenden, wenn Sie HoneyComb Sdk (API Level 11) verwenden.

view.setX(float x);

Parameter x ist die visuelle x-Position dieser Ansicht.

view.setY(float y);

Der Parameter y ist die visuelle y-Position dieser Ansicht.

Ich hoffe es wird dir hilfreich sein. :) :)

Huhn mit Reis
quelle
4
Ich arbeite an 2.2 Froyo und diese Methoden sind darin nicht verfügbar.
Arun Badole
7

Zur Unterstützung aller API-Ebenen können Sie es folgendermaßen verwenden:

ViewPropertyAnimator.animate(view).translationYBy(-yourY).translationXBy(-yourX).setDuration(0);
Orr
quelle
Weil er die Position ändern möchte und die obige Lösung besser ist und keine Animation benötigt
FireZenk
Außerdem kann die Übersetzung dazu führen, dass die Ansicht (teilweise) vom Bildschirm
abweicht
4

Legen Sie die linke Position dieser Ansicht relativ zum übergeordneten Element fest:

view.setLeft(int leftPosition);

Legen Sie die richtige Position dieser Ansicht relativ zum übergeordneten Element fest:

view.setRight(int rightPosition);

Legen Sie die oberste Position dieser Ansicht relativ zum übergeordneten Element fest:

view.setTop(int topPosition);

Legen Sie die untere Position dieser Ansicht relativ zum übergeordneten Element fest:

view.setBottom(int bottomPositon);

Die obigen Methoden werden verwendet, um die Position der Ansicht in Bezug auf das übergeordnete Element festzulegen.

Balaji.K
quelle
Entschuldigung Diese Methoden sind nicht verfügbar. Können Sie mir einen Code senden?
Arun Badole
4
"Diese Methode soll vom Layoutsystem aufgerufen werden und sollte im Allgemeinen nicht anders aufgerufen werden, da die Eigenschaft jederzeit durch das Layout geändert werden kann."
GDanger
4

Verwenden Sie LayoutParams. Wenn Sie ein LinearLayout verwenden, müssen Sie android.widget.LinearLayout.LayoutParams importieren. Andernfalls importieren Sie die richtige Version von LayoutParams für das von Ihnen verwendete Layout. Andernfalls wird eine ClassCastException ausgelöst .

LayoutParams layoutParams = new LayoutParams(int width, int height);
layoutParams.setMargins(int left, int top, int right, int bottom);
imageView.setLayoutParams(layoutParams);

NB: Beachten Sie, dass Sie auch imageView.setLeft (int dim) verwenden können, ABER DIESES wird NICHT die Position der Komponente festlegen, sondern nur die Position des linken Randes der Komponente, der Rest bleibt an derselben Position .

Alessandro Muzzi
quelle
Wie können wir die Ansicht an eine bestimmte Position verschieben, ohne die ursprüngliche Ansicht zu beeinträchtigen?
James
Ich bin nicht sicher, ob ich Ihr Problem verstanden habe, denn wenn Sie eine Ansicht verschieben möchten, ändern Sie sie dadurch, dass Sie sie verschieben. Wenn Sie eine Ansicht unabhängig davon über eine andere verschieben möchten, benötigen Sie möglicherweise eine FrameLayout-Ansicht, die Ihr Hauptlayout durchbrennt. Dann können Sie darin Ihre unabhängigen Ansichten platzieren (natürlich, wenn Sie möchten, dass sie sich unter Ihrer Hauptansicht bewegen müssen das FrameLayout vor Ihrem Haupt-Layout platzieren)
Alessandro Muzzi
3

Verwenden Sie RelativeLayout, platzieren Sie Ihre Ansicht darin, holen Sie sich ein RelativeLayout.LayoutParamsObjekt aus Ihrer Ansicht und legen Sie die Ränder nach Bedarf fest. Dann rufen Sie requestLayout()Ihre Ansicht an. Dies ist der einzige Weg, den ich kenne.

Glodos
quelle
1

Ich fand, dass @Stefan Haustein meiner Erfahrung sehr nahe kommt, aber nicht 100% sicher ist. Mein Vorschlag ist:

  • setLeft()/ setRight()/ setBottom()/ setTop()Wird manchmal nicht funktionieren.
  • Wenn Sie beim Hinzufügen und Anzeigen der Ansicht vorübergehend eine Position festlegen möchten (z. B. für Animationen, die keine Hierarchie betreffen) , verwenden Sie stattdessen / . (Vielleicht möchten Sie mehr in Unterschied und suchensetX()setY()setLeft()setX() )
  • Beachten Sie, dass X, Y absolut zu sein scheinen und von AbsoluteLayout unterstützt wurden, das jetzt veraltet ist. Sie haben also das Gefühl, dass X, Y wahrscheinlich nicht mehr unterstützt wird. Und ja, aber nur teilweise. Wenn Ihre Ansicht hinzugefügt wird, funktioniert setX (), setY () einwandfrei . andernfalls, wenn Sie versuchen, einen Blick in die Ansicht Gruppe Layout hinzufügen (zB FrameLayout, Linearlayout , RelativeLayout), Sie müssen eingestellt seine LayoutParams mit margin, MarginTop statt (setX (), Sethos () in diesem Fall nicht funktionieren manchmal).
  • Das Festlegen der Position der Ansicht mit marginLeft und marginTop ist ein nicht synchronisierter Prozess. Es braucht also etwas Zeit, um die Hierarchie zu aktualisieren . Wenn Sie die Ansicht sofort nach dem festgelegten Rand verwenden , erhalten Sie möglicherweise einen falschen Wert .
Nguyen Tan Dat
quelle
0

Bei der Positionierung ist zu beachten, dass jede Ansicht einen Index relativ zu ihrer übergeordneten Ansicht hat. Wenn Sie also ein lineares Layout mit drei Unteransichten haben, haben die Unteransichten jeweils einen Index: 0, 1, 2 im obigen Fall.

Auf diese Weise können Sie der letzten Position (oder dem Ende) in einer übergeordneten Ansicht eine Ansicht hinzufügen, indem Sie Folgendes tun:

int childCount = parent.getChildCount();
parentView.addView(newView, childCount);

Alternativ können Sie eine Ansicht durch Folgendes ersetzen:

int childIndex = parentView.indexOfChild(childView);
childView.setVisibility(View.GONE);

parentView.addView(newView, childIndex);
Braden Holt
quelle