How can I dynamically set the position of view in Android?
Asked Answered
J

13

119

How can I change the position of view through code? Like changing its X, Y position. Is it possible?

Johnsson answered 30/6, 2011 at 13:39 Comment(0)
S
123

For anything below Honeycomb (API Level 11) you'll have to use setLayoutParams(...).

If you can limit your support to Honeycomb and up you can use the setX(...), setY(...), setLeft(...), setTop(...), etc.

Snath answered 29/6, 2012 at 22:48 Comment(1)
from the docs of 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. - so maybe thats not that good an idea ;)Defile
V
51

Yes, you can dynamically set the position of the view in Android. Likewise, you have an ImageView in LinearLayout of your XML file. So you can set its position through LayoutParams.But make sure to take LayoutParams according to the layout taken in your XML file. There are different LayoutParams according to the layout taken.

Here is the code to set:

    LayoutParams layoutParams=new LayoutParams(int width, int height);
    layoutParams.setMargins(int left, int top, int right, int bottom);
    imageView.setLayoutParams(layoutParams);
Viaticum answered 24/5, 2012 at 11:13 Comment(4)
also note that you must import android.widget.LinearLayout.LayoutParams; because the default is ViewGroup's LayoutParamsBoykins
This does not seem to be working on Android 8+. have you faced a similar problem?Constancy
Any idea why the Andriod designers go to such trouble to keep the progammers from using X,Y to position things. Eventually everything has to be drawn that way. This suggests that Android is being designed by people who can't code.Griddle
What if we don't know the parent layout type?Symploce
G
45

There are different valid answers already, but none seems to properly suggest which method(s) to use in which case, except for the corresponding API level restrictions:

  • If you can wait for a layout cycle and the parent view group supports MarginLayoutParams (or a subclass), set marginLeft / marginTop accordingly.

  • If you need to change the position immediately and persistently (e.g. for a PopupMenu anchor), additionally call layout(l, t, r, b) with the same coordinates. This preempts what the layout system will confirm later.

  • For immediate (temporary) changes (such as animations), use setX() / setY() instead. In cases where the parent size doesn't depend on WRAP_CHILDREN, it might be fine to use setX() / setY() exclusively.

  • Never use setLeft() / setRight() / setBottom() / setTop(), see below.

Background: The mLeft / mTop / mBottom / mRight fields get filled from the corresponding LayoutParams in layout(). Layout is called implicitly and asynchronously by the Android view layout system. Thus, setting the MarginLayoutParams seems to be the safest and cleanest way to set the position permanently. However, the asynchronous layout lag might be a problem in some cases, e.g. when using a View to render a cursor, and it's supposed to be re-positioned and serve as a PopupMenu anchor at the same time. In this case, calling layout() worked fine for me.

The problems with setLeft() and setTop() are:

  • Calling them alone is not sufficient -- you also need to call setRight() and setBottom() to avoid stretching or shrinking the view.

  • The implementation of these methods looks relatively complex (= doing some work to account for the view size changes caused by each of them)

  • They seem to cause strange issues with input fields: EditText soft numeric keyboard sometimes does not allow digits

setX() and setY() work outside of the layout system, and the corresponding values are treated as an additional offset to the left / top / bottom / right values determined by the layout system, shifting the view accordingly. They seem to have been added for animations (where an immediate effect without going through a layout cycle is required).

Gallinaceous answered 16/1, 2017 at 14:42 Comment(6)
Hello Stefan. Could you advice few books or articles where I can understand how the android layout system work. I understand that sequence of layout() onMeasure() onDraw() calls, but want to know it more details. Thanks in advanceHushhush
Unfortunately I can't -- the best and most definitive reference seems to be the actual Android source code O:)Gallinaceous
I use setY to change view ,it it change in next layout cycle , not immediate ?Leix
How did you determine this?Gallinaceous
It's worth pointing out that the marginLeft can be set by using setLayoutParams with a new FrameLayout.LayoutParams(width, height) on which you set the marginLeftReposeful
Isn't that already covered by "MarginLayoutParams or a subclass"?Gallinaceous
D
19

There is a library called NineOldAndroids, which allows you to use the Honeycomb animation library all the way down to version one.

This means you can define left, right, translationX/Y with a slightly different interface.

Here is how it works:

ViewHelper.setTranslationX(view, 50f);

You just use the static methods from the ViewHelper class, pass the view and which ever value you want to set it to.

Demography answered 25/7, 2013 at 17:5 Comment(0)
N
17

I would recommend using setTranslationX and setTranslationY. I'm only just getting started on this myself, but these seem to be the safest and preferred way of moving a view. I guess it depends a lot on what exactly you're trying to do, but this is working well for me for 2D animation.

Nigelniger answered 3/9, 2012 at 19:25 Comment(0)
J
16

You can try to use the following methods, if you're using HoneyComb Sdk(API Level 11).

view.setX(float x);

Parameter x is the visual x position of this view.

view.setY(float y);

Parameter y is the visual y position of this view.

I hope it will be helpful to you. :)

Jota answered 30/6, 2011 at 15:17 Comment(1)
I am working on 2.2 Froyo and these methods are not a available in it.Johnsson
E
8

For support to all API levels you can use it like this:

ViewPropertyAnimator.animate(view).translationYBy(-yourY).translationXBy(-yourX).setDuration(0);
Enyo answered 26/1, 2015 at 14:23 Comment(2)
Because he want to change the position and above solution is better and not need animationWidely
Also, translation may cause the view to go (partially) off-screenCarlitacarlo
D
4

Set the left position of this view relative to its parent:

view.setLeft(int leftPosition);

Set the right position of this view relative to its parent:

view.setRight(int rightPosition);

Set the top position of this view relative to its parent:

view.setTop(int topPosition);

Set the bottom position of this view relative to its parent:

view.setBottom(int bottomPositon);

The above methods are used to set the position the view related to its parent.

Dichotomize answered 30/6, 2011 at 13:55 Comment(2)
Sorry These methods are not available.Can you send me any code?Johnsson
"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."Koan
S
4

Use LayoutParams. If you are using a LinearLayout you have to import android.widget.LinearLayout.LayoutParams, else import the proper version of LayoutParams for the layout you're using, or it will cause a ClassCastException, then:

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

NB: Note that you can use also imageView.setLeft(int dim), BUT THIS WON'T set the position of the component, it will set only the position of the left border of the component, the rest will remain at the same position.

Stearin answered 8/4, 2014 at 9:14 Comment(2)
so how can we move the view to specific position without impacting original view?Radii
I'm not sure I've understood your problem because if you want to move a view you will change it by the fact you're moving it. Anyway, if you want to move a view over another independently from it, you may need a FrameLayout view bleow your main layout then, inside of it, you can place your independent views (obviously if you want it to move under your main view you have to place the FrameLayout before your main one)Stearin
E
3

Use RelativeLayout, place your view in it, get RelativeLayout.LayoutParams object from your view and set margins as you need. Then call requestLayout() on your view. This is the only way I know.

Ebsen answered 12/11, 2011 at 9:28 Comment(0)
C
3

In Kotlin you can do it as below;

view
    .animate()
    .x(50f)
    .y(100f)
    .duration = 500L
Contraption answered 6/7, 2021 at 9:7 Comment(0)
A
2

I found that @Stefan Haustein comes very close to my experience, but not sure 100%. My suggestion is:

  • setLeft() / setRight() / setBottom() / setTop() won't work sometimes.
  • If you want to set a position temporarily (e.g for doing animation, not affected a hierachy) when the view was added and shown, just use setX()/ setY() instead. (You might want search more in difference setLeft() and setX())
  • And note that X, Y seem to be absolute, and it was supported by AbsoluteLayout which now is deprecated. Thus, you feel X, Y is likely not supported any more. And yes, it is, but only partly. It means if your view is added, setX(), setY() will work perfectly; otherwise, when you try to add a view into view group layout (e.g FrameLayout, LinearLayout, RelativeLayout), you must set its LayoutParams with marginLeft, marginTop instead (setX(), setY() in this case won't work sometimes).
  • Set position of the view by marginLeft and marginTop is an unsynchronized process. So it needs a bit time to update hierarchy. If you use the view straight away after set margin for it, you might get a wrong value.
Amaryllis answered 23/8, 2018 at 4:6 Comment(0)
S
0

One thing to keep in mind with positioning is that each view has an index relative to its parent view. So if you have a linear layout with three subviews, the subviews will each have an index: 0, 1, 2 in the above case.

This allows you to add a view to the last position (or the end) in a parent view by doing something like this:

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

Alternatively you could replace a view using something like the following:

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

parentView.addView(newView, childIndex);
Stanchion answered 15/10, 2019 at 19:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.