Comment puis-je définir dynamiquement la position de vue dans Android?

102

Comment puis-je changer la position de la vue via le code? Comme changer sa position X, Y. C'est possible?

Arun Badole
la source

Réponses:

117

Pour tout ce qui est en dessous de Honeycomb (niveau d'API 11), vous devrez utiliser setLayoutParams(...).

Si vous pouvez limiter votre soutien à nid d' abeille et en vous pouvez utiliser setX(...), setY(...), setLeft(...), setTop(...), etc.

Dave périssable
la source
40
de la documentation de 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.- alors peut-être que ce n'est pas une bonne idée;)
katzenhut
47

Oui, vous pouvez définir dynamiquement la position de vue sous Android. De même, vous avez un ImageViewin LinearLayoutde votre fichier xml.Vous pouvez donc définir sa position via LayoutParams.Mais assurez-vous de prendre en LayoutParamsfonction de la mise en page prise dans votre fichier xml.Il y en a différentes LayoutParamsselon la mise en page prise.

Voici le code à définir:

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

J'espère qu'il vous sera utile de vous positionner.

AkashG
la source
15
notez également que vous devez importer android.widget.LinearLayout.LayoutParams; car la valeur par défaut est LayoutParams de ViewGroup
David T.
Cela ne semble pas fonctionner sur Android 8+. avez-vous rencontré un problème similaire?
MyFlashLab
N'importe quelle idée pourquoi les concepteurs d'Andriod se donnent tant de mal pour empêcher les programmeurs d'utiliser X, Y pour positionner les choses. Finalement, tout doit être dessiné de cette façon. Cela suggère qu'Android est conçu par des personnes qui ne peuvent pas coder.
Paul McCarthy
33

Il existe déjà différentes réponses valides, mais aucune ne semble suggérer correctement la ou les méthodes à utiliser, auquel cas, à l'exception des restrictions de niveau d'API correspondantes:

  • Si vous pouvez attendre un cycle de mise en page et que le groupe de vues parent prend en charge MarginLayoutParams(ou une sous-classe), définissez marginLeft/ en marginTopconséquence.

  • Si vous avez besoin de changer la position immédiatement et de manière persistante (par exemple pour une ancre PopupMenu), appelez en plus layout(l, t, r, b)avec les mêmes coordonnées. Cela prévient ce que le système de mise en page confirmera plus tard.

  • Pour les modifications immédiates (temporaires) (telles que les animations), utilisez setX()/ à la setY()place. Dans les cas où la taille du parent ne dépend pas de WRAP_CHILDREN, il peut être bon d'utiliser setX()/ setY()exclusivement.

  • Ne jamais utiliser setLeft()/ setRight()/ setBottom()/ setTop(), voir ci - dessous.

Contexte : Les champs mLeft/ mTop/ mBottom/ mRightsont remplis à partir des LayoutParams correspondants dans layout (). La mise en page est appelée implicitement et de manière asynchrone par le système de mise en page de vue Android. Ainsi, le réglage MarginLayoutParamssemble être le moyen le plus sûr et le plus propre de régler la position de façon permanente. Cependant, le décalage de disposition asynchrone peut être un problème dans certains cas, par exemple lors de l'utilisation d'une vue pour rendre un curseur, et il est supposé être repositionné et servir en même temps d'ancre PopupMenu. Dans ce cas, l'appel layout()a bien fonctionné pour moi.

Les problèmes avec setLeft()et setTop()sont:

  • Les appeler seuls ne suffit pas - vous devez également appeler setRight()et setBottom()éviter d'étirer ou de réduire la vue.

  • La mise en œuvre de ces méthodes semble relativement complexe (= faire du travail pour tenir compte des changements de taille de vue causés par chacune d'elles)

  • Ils semblent causer des problèmes étranges avec les champs de saisie: le clavier numérique souple EditText n'autorise parfois pas les chiffres

setX()et setY()travailler en dehors du système de mise en page, et les valeurs correspondantes sont traitées comme un décalage supplémentaire vers les valeurs gauche / haut / bas / droite déterminées par le système de mise en page, décalant la vue en conséquence. Ils semblent avoir été ajoutés pour les animations (où un effet immédiat sans passer par un cycle de mise en page est requis).

Stefan Haustein
la source
Bonjour Stefan. Pourriez-vous me conseiller quelques livres ou articles où je peux comprendre le fonctionnement du système de mise en page Android. Je comprends cette séquence d'appels à layout () onMeasure () onDraw (), mais je veux en savoir plus. Merci d'avance
Sergey Brazhnik
Malheureusement, je ne peux pas - la référence la meilleure et la plus définitive semble être le code source Android actuel O :)
Stefan Haustein
J'utilise setY pour changer de vue, cela change-t-il dans le prochain cycle de mise en page, pas immédiat?
signal du
Comment avez-vous déterminé cela?
Stefan Haustein
Il convient de souligner que le marginLeftpeut être défini en utilisant setLayoutParamsavec un new FrameLayout.LayoutParams(width, height)sur lequel vous définissez lemarginLeft
lucidbrot
18

Il existe une bibliothèque appelée NineOldAndroids , qui vous permet d'utiliser la bibliothèque d'animation Honeycomb jusqu'à la première version.

Cela signifie que vous pouvez définir gauche, droite, translationX / Y avec une interface légèrement différente.

Voici comment cela fonctionne:

ViewHelper.setTranslationX(view, 50f);

Vous utilisez simplement les méthodes statiques de la classe ViewHelper, passez la vue et la valeur à laquelle vous souhaitez la définir.

Ben
la source
16

Je recommanderais d'utiliser setTranslationXet setTranslationY. Je ne fais que commencer moi-même, mais cela semble être le moyen le plus sûr et le plus préféré de déplacer une vue. Je suppose que cela dépend beaucoup de ce que vous essayez de faire exactement, mais cela fonctionne bien pour moi pour l'animation 2D.

Brianmearns
la source
13

Vous pouvez essayer d'utiliser les méthodes suivantes, si vous utilisez HoneyComb Sdk (API niveau 11).

view.setX(float x);

Le paramètre x est la position visuelle x de cette vue.

view.setY(float y);

Le paramètre y est la position visuelle y de cette vue.

J'espère que cela vous sera utile. :)

Riz au poulet
la source
4
Je travaille sur 2.2 Froyo et ces méthodes ne sont pas disponibles.
Arun Badole
7

Vous pouvez utiliser pour le soutien à tous les niveaux de l' API , il présente comme suit:

ViewPropertyAnimator.animate(view).translationYBy(-yourY).translationXBy(-yourX).setDuration(0);
Orr
la source
Parce qu'il veut changer de position et que la solution ci-dessus est meilleure et n'a pas besoin d'animation
FireZenk
En outre, la traduction peut entraîner un affichage (partiellement) hors de l'écran
mewa
4

Définissez la position gauche de cette vue par rapport à son parent:

view.setLeft(int leftPosition);

Définissez la bonne position de cette vue par rapport à son parent:

view.setRight(int rightPosition);

Définissez la position supérieure de cette vue par rapport à son parent:

view.setTop(int topPosition);

Définissez la position inférieure de cette vue par rapport à son parent:

view.setBottom(int bottomPositon);

Les méthodes ci-dessus sont utilisées pour définir la position de la vue liée à son parent.

Balaji.K
la source
Désolé Ces méthodes ne sont pas disponibles, pouvez-vous m'envoyer un code?
Arun Badole
4
"Cette méthode est destinée à être appelée par le système de mise en page et ne doit généralement pas être appelée autrement, car la propriété peut être modifiée à tout moment par la mise en page."
GDanger
4

Utilisez LayoutParams. Si vous utilisez un LinearLayout, vous devez importer android.widget.LinearLayout.LayoutParams, sinon importez la version appropriée de LayoutParams pour la mise en page que vous utilisez, sinon cela provoquera une ClassCastException , alors:

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

NB: Notez que vous pouvez également utiliser imageView.setLeft (int dim), MAIS CELA NE fixera PAS la position du composant, il ne définira que la position du bord gauche du composant, le reste restera à la même position .

Alessandro Muzzi
la source
alors comment pouvons-nous déplacer la vue vers une position spécifique sans affecter la vue d'origine?
james
Je ne suis pas sûr d'avoir compris votre problème car si vous souhaitez déplacer une vue, vous la modifierez par le fait que vous la déplacez. Quoi qu'il en soit, si vous souhaitez déplacer une vue sur une autre indépendamment de celle-ci, vous devrez peut-être une vue FrameLayout pour faire exploser votre mise en page principale, puis, à l'intérieur de celle-ci, vous pouvez placer vos vues indépendantes (évidemment si vous voulez qu'elle se déplace sous votre vue principale, vous devez placer le FrameLayout avant votre principal)
Alessandro Muzzi
3

Utilisez RelativeLayout, placez votre vue dedans, récupérez un RelativeLayout.LayoutParamsobjet de votre vue et définissez les marges selon vos besoins. Appelez ensuite requestLayout()votre vue. C'est le seul moyen que je connaisse.

glodos
la source
1

J'ai trouvé que @Stefan Haustein est très proche de mon expérience, mais pas sûr à 100%. Ma suggestion est:

  • setLeft()/ setRight()/ setBottom()/ setTop()ne fonctionnera pas parfois.
  • Si vous souhaitez définir une position temporairement (par exemple pour faire de l'animation, sans affecter une hiérarchie) lorsque la vue a été ajoutée et affichée , utilisezsetX()setY() simplement / à la place. (Vous voudrez peut-être rechercher plus de différence setLeft()etsetX() )
  • Et notez que X, Y semblent être absolus, et il a été pris en charge par AbsoluteLayout qui est maintenant obsolète. Ainsi, vous pensez que X, Y n'est probablement plus pris en charge. Et oui, mais seulement en partie. Cela signifie que si votre vue est ajoutée, setX (), setY () fonctionnera parfaitement ; sinon, lorsque vous essayez d' ajouter une vue dans la disposition du groupe de vues (par exemple FrameLayout, LinearLayout, RelativeLayout), vous devez définir ses LayoutParams avec marginLeft, marginTop à la place (setX (), setY () dans ce cas ne fonctionnera pas parfois).
  • Définir la position de la vue par marginLeft et marginTop est un processus non synchronisé . Il faut donc un peu de temps pour mettre à jour la hiérarchie . Si vous utilisez la vue immédiatement après avoir défini la marge pour celle-ci, vous risquez d'obtenir une valeur erronée .
Nguyen Tan Dat
la source
0

Une chose à garder à l'esprit avec le positionnement est que chaque vue a un index par rapport à sa vue parente. Donc, si vous avez une mise en page linéaire avec trois sous-vues, les sous-vues auront chacune un index: 0, 1, 2 dans le cas ci-dessus.

Cela vous permet d'ajouter une vue à la dernière position (ou à la fin) dans une vue parent en faisant quelque chose comme ceci:

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

Vous pouvez également remplacer une vue en utilisant quelque chose comme ce qui suit:

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

parentView.addView(newView, childIndex);
Braden Holt
la source