Come posso impostare dinamicamente la posizione di visualizzazione in Android?


102

Come posso modificare la posizione di visualizzazione tramite codice? Come cambiare la sua posizione X, Y. È possibile?

Risposte:


117

Per qualsiasi cosa al di sotto di Honeycomb (livello API 11) dovrai usare setLayoutParams(...).

Se è possibile limitare il vostro sostegno a nido d'ape e fino si può usare il setX(...), setY(...), setLeft(...), setTop(...), etc.


40
dai documenti di 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.- quindi forse non è un'idea così buona;)
katzenhut

47

Sì, puoi impostare dinamicamente la posizione di visualizzazione in Android. Allo stesso modo hai un ImageViewin LinearLayoutdel tuo file xml, quindi puoi impostarne la posizione tramite LayoutParams.Ma assicurati di prendere in LayoutParamsbase al layout preso nel tuo file xml. Ce ne sono diversi a LayoutParamsseconda del layout preso.

Ecco il codice da impostare:

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

Spero che ti sarà utile impostare la posizione.


15
si noti inoltre che è necessario importare android.widget.LinearLayout.LayoutParams; perché l'impostazione predefinita è LayoutParams di ViewGroup
David T.

Questo non sembra funzionare su Android 8+. hai affrontato un problema simile?
MyFlashLab

Qualche idea sul perché i designer di Andriod si diano tanto da fare per impedire ai programmatori di usare X, Y per posizionare le cose. Alla fine tutto deve essere disegnato in quel modo. Ciò suggerisce che Android è stato progettato da persone che non possono programmare.
Paul McCarthy,

33

Esistono già diverse risposte valide, ma nessuna sembra suggerire correttamente quale metodo (i) utilizzare, nel qual caso, ad eccezione delle corrispondenti restrizioni a livello di API:

  • Se puoi attendere un ciclo di layout e il gruppo di viste padre supporta MarginLayoutParams(o una sottoclasse), imposta marginLeft/ di marginTopconseguenza.

  • Se è necessario modificare la posizione immediatamente e in modo persistente (ad esempio per un'ancora PopupMenu), chiamare in aggiunta layout(l, t, r, b)con le stesse coordinate. Ciò prevale su ciò che il sistema di layout confermerà in seguito.

  • Per modifiche immediate (temporanee) (come le animazioni), usa setX()/ setY()invece. Nei casi in cui la dimensione del genitore non dipende da WRAP_CHILDREN, potrebbe andare bene usare setX()/ setY()esclusivamente.

  • Non usare maisetLeft() / setRight()/ setBottom()/ setTop(), vedi sotto.

Sfondo : i campi mLeft/ mTop/ mBottom/ mRightvengono riempiti dai LayoutParams corrispondenti in layout (). Il layout viene chiamato in modo implicito e asincrono dal sistema di layout di visualizzazione di Android. Pertanto, l'impostazione di MarginLayoutParamssembra essere il modo più sicuro e pulito per impostare la posizione in modo permanente. Tuttavia, il ritardo del layout asincrono potrebbe essere un problema in alcuni casi, ad esempio quando si utilizza una vista per eseguire il rendering di un cursore, e dovrebbe essere riposizionato e allo stesso tempo fungere da ancoraggio PopupMenu. In questo caso, la chiamata ha layout()funzionato bene per me.

I problemi con setLeft()e setTop()sono:

  • Chiamarli da soli non è sufficiente: devi anche chiamare setRight()ed setBottom()evitare di allungare o restringere la vista.

  • L'implementazione di questi metodi sembra relativamente complessa (= fare del lavoro per tenere conto delle modifiche alle dimensioni della vista causate da ciascuno di essi)

  • Sembrano causare strani problemi con i campi di input: la tastiera numerica morbida EditText a volte non consente le cifre

setX()e setY()lavorare al di fuori del sistema di layout, ei valori corrispondenti vengono trattati come un offset aggiuntivo rispetto ai valori sinistro / superiore / inferiore / destro determinati dal sistema di layout, spostando la vista di conseguenza. Sembra che siano stati aggiunti per le animazioni (dove è richiesto un effetto immediato senza passare attraverso un ciclo di layout).


Ciao Stefan. Potresti consigliare alcuni libri o articoli in cui posso capire come funziona il sistema di layout Android. Capisco quella sequenza di chiamate layout () onMeasure () onDraw (), ma voglio saperne di più in dettaglio. Grazie in anticipo
Sergey Brazhnik

Sfortunatamente non posso - il riferimento migliore e più definitivo sembra essere l'attuale codice sorgente di Android O :)
Stefan Haustein

Uso setY per cambiare vista, cambia nel prossimo ciclo di layout, non immediato?
segnale

Come l'hai determinato?
Stefan Haustein

Vale la pena sottolineare che il marginLeftpuò essere impostato utilizzando setLayoutParamscon a new FrameLayout.LayoutParams(width, height)su cui si imposta ilmarginLeft
lucidbrot

18

C'è una libreria chiamata NineOldAndroids , che ti consente di utilizzare la libreria di animazione Honeycomb fino alla versione uno.

Ciò significa che puoi definire sinistra, destra, translationX / Y con un'interfaccia leggermente diversa.

Ecco come funziona:

ViewHelper.setTranslationX(view, 50f);

Devi solo usare i metodi statici della classe ViewHelper, passare la vista e il valore su cui vuoi impostarla.


16

Consiglierei di usare setTranslationXe setTranslationY. Sto solo iniziando da solo, ma questo sembra essere il modo più sicuro e preferito per spostare una visualizzazione. Immagino che dipenda molto da cosa stai cercando di fare, ma per me funziona bene per l'animazione 2D.


13

Puoi provare a utilizzare i seguenti metodi, se stai utilizzando HoneyComb Sdk (livello API 11).

view.setX(float x);

Il parametro x è la posizione x visiva di questa vista.

view.setY(float y);

Il parametro y è la posizione y visiva di questa vista.

Spero che ti sarà utile. :)


4
Sto lavorando su 2.2 Froyo e questi metodi non sono disponibili in esso.
Arun Badole

7

Per il supporto a tutti i livelli API puoi usarlo in questo modo:

ViewPropertyAnimator.animate(view).translationYBy(-yourY).translationXBy(-yourX).setDuration(0);

Perché vuole cambiare la posizione e sopra la soluzione è migliore e non ha bisogno di animazione
FireZenk

Inoltre, la traduzione può causare la visualizzazione (parzialmente) fuori campo
mewa

4

Imposta la posizione sinistra di questa vista rispetto al suo genitore:

view.setLeft(int leftPosition);

Imposta la posizione corretta di questa vista rispetto al suo genitore:

view.setRight(int rightPosition);

Imposta la prima posizione di questa vista rispetto al suo genitore:

view.setTop(int topPosition);

Imposta la posizione inferiore di questa vista rispetto al suo genitore:

view.setBottom(int bottomPositon);

I metodi precedenti vengono utilizzati per impostare la posizione della vista relativa al suo genitore.


Spiacenti, questi metodi non sono disponibili, puoi inviarmi un codice?
Arun Badole

4
"Questo metodo è pensato per essere chiamato dal sistema di layout e generalmente non dovrebbe essere chiamato altrimenti, perché la proprietà può essere modificata in qualsiasi momento dal layout."
GDanger

4

Usa LayoutParams. Se stai usando un LinearLayout devi importare android.widget.LinearLayout.LayoutParams, altrimenti importa la versione corretta di LayoutParams per il layout che stai usando, o causerà un'eccezione ClassCastException , quindi:

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

NB: Nota che puoi usare anche imageView.setLeft (int dim), MA QUESTO NON imposterà la posizione del componente, imposterà solo la posizione del bordo sinistro del componente, il resto rimarrà nella stessa posizione .


quindi come possiamo spostare la vista in una posizione specifica senza influire sulla vista originale?
james

Non sono sicuro di aver capito il tuo problema perché se vuoi spostare una vista, la cambierai dal fatto che la stai spostando. Ad ogni modo, se vuoi spostare una vista su un'altra indipendentemente da essa, potresti aver bisogno di una vista FrameLayout che esponga il tuo layout principale quindi, al suo interno, puoi posizionare le tue viste indipendenti (ovviamente se vuoi che si muova sotto la tua vista principale tu devi posizionare il FrameLayout prima di quello principale)
Alessandro Muzzi

3

Usa RelativeLayout, posiziona la tua vista al suo interno, ottieni l' RelativeLayout.LayoutParamsoggetto dalla tua vista e imposta i margini di cui hai bisogno. Quindi chiama requestLayout()il tuo punto di vista. Questo è l'unico modo che conosco.


1

Ho scoperto che @Stefan Haustein si avvicina molto alla mia esperienza, ma non ne sono sicuro al 100%. Il mio suggerimento è:

  • setLeft()/ setRight()/ setBottom()/ setTop()a volte non funzionerà.
  • Se vuoi impostare una posizione temporaneamente (ad esempio per fare un'animazione, non influenzare una gerarchia) quando la vista è stata aggiunta e mostrata , usasetX()setY() semplicemente / invece. (Potresti voler cercare più in differenza setLeft()esetX() )
  • E nota che X, Y sembrano essere assoluti ed è stato supportato da AbsoluteLayout che ora è deprecato. Quindi, ritieni che X, Y probabilmente non sia più supportato. E sì, lo è, ma solo in parte. Significa che se la tua vista viene aggiunta, setX (), setY () funzioneranno perfettamente ; altrimenti, quando si tenta di aggiungere una vista nel layout del gruppo di viste (ad esempio FrameLayout, LinearLayout, RelativeLayout), è necessario impostare i suoi LayoutParams con marginLeft, marginTop invece (setX (), setY () in questo caso a volte non funzionerà).
  • Imposta la posizione della vista tramite marginLeft e marginTop è un processo non sincronizzato . Quindi ci vuole un po 'di tempo per aggiornare la gerarchia . Se utilizzi la vista subito dopo aver impostato il margine , potresti ottenere un valore errato .

0

Una cosa da tenere a mente con il posizionamento è che ogni vista ha un indice relativo alla sua vista principale. Quindi, se hai un layout lineare con tre sottoview, le sottoview avranno ciascuna un indice: 0, 1, 2 nel caso precedente.

Ciò ti consente di aggiungere una vista all'ultima posizione (o alla fine) in una vista genitore facendo qualcosa del genere:

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

In alternativa puoi sostituire una vista usando qualcosa di simile al seguente:

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

parentView.addView(newView, childIndex);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.