添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

如何在Android中动态地设置视图的位置?

114 人关注

我怎样才能通过代码改变视图的位置?比如改变它的X、Y位置。这可能吗?

android
layout
view
Arun Badole
Arun Badole
发布于 2011-06-30
13 个回答
Perishable Dave
Perishable Dave
发布于 2019-10-16
已采纳
0 人赞同

对于低于Honeycomb(API级别11)的东西,你必须使用 setLayoutParams(...)

如果你能将你的支持限制在Honeycomb及以上,你可以使用 setX(...) setY(...) setLeft(...) setTop(...) 等。

from the docs of setTop() developer.android.com/reference/android/view/... :替换代码0- 所以,也许这不是一个好主意;)
AkashG
AkashG
发布于 2019-10-16
0 人赞同

是的,你可以在Android中动态地设置视图的位置。同样地,你的XML文件的 LinearLayout 中有一个 ImageView 。所以你可以通过 LayoutParams 来设置它的位置。但要确保根据你的XML文件中的布局来采取 LayoutParams 。根据所采取的布局,有不同的 LayoutParams

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);
    
还要注意,你必须导入android.widget.LinearLayout.LayoutParams;因为默认是ViewGroup的LayoutParams。
这在安卓8+系统上似乎并不奏效。你是否遇到过类似的问题?
知道为什么Andriod的设计者要如此麻烦地阻止程序员使用X、Y来定位东西吗?最终,所有的东西都必须以这种方式绘制。这表明,安卓系统是由不会编码的人设计的。
Stefan Haustein
Stefan Haustein
发布于 2019-10-16
0 人赞同

已经有了不同的有效答案,但除了相应的API级别的限制外,似乎都没有正确地建议在什么情况下使用哪种(些)方法。

  • 如果你可以等待一个布局周期,并且父级视图组支持 MarginLayoutParams (或子类),请设置 marginLeft 。/ marginTop

  • 如果你需要立即和持续地改变位置(例如对于一个PopupMenu锚),另外调用 layout(l, t, r, b) ,坐标相同。这样就可以抢占布局系统稍后确认的位置。

  • 对于即时(临时)变化(如动画),使用 setX() 。/ setY() 代替。在父类的大小不依赖于WRAP_CHILDREN的情况下,使用 setX() / setY() 就可以了。/ setY()

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

  • 背景介绍 : 【替换代码12/ 【替换代码13/ 【替换代码14/ mRight 字段由layout()中相应的LayoutParams填充。布局是由Android视图布局系统隐含地、异步地调用的。因此,设置 MarginLayoutParams 似乎是永久设置位置的最安全、最干净的方式。然而,在某些情况下,异步布局滞后可能是一个问题,例如,当使用视图渲染光标时,它应该被重新定位并同时作为PopupMenu的锚。在这种情况下,调用 layout() 对我来说很有效。

    setLeft() setTop() 的问题是。

  • 仅仅调用它们是不够的--你还需要调用 setRight() setBottom() 以避免拉伸或缩小视图。

  • 这些方法的实现看起来相对复杂(=做了一些工作来解释每个方法引起的视图大小变化)

  • 它们似乎会引起输入字段的奇怪问题。 编辑文本软数字键盘有时不允许有数字

  • 替换代码4】和 setY() 在布局系统之外工作,相应的值被视为布局系统确定的左/上/下/右值的额外偏移,相应地移动视图。它们似乎是为动画添加的(在这种情况下,需要不经过布局循环就能立即产生效果)。

    你好,Stefan。你能不能给我一些书或文章,让我了解安卓的布局系统是如何工作的。我明白布局()onMeasure()onDraw()的调用顺序,但我想知道更多细节。谢谢
    不幸的是,我不能 -- 最好和最确定的参考似乎是实际的安卓源代码O:)
    我使用setY来改变视图,它是在下一个布局周期改变,而不是立即改变?
    How did you determine this?
    值得指出的是, marginLeft 可以通过使用 setLayoutParams new FrameLayout.LayoutParams(width, height) 来设置,在此基础上设置 marginLeft
    Ben
    Ben
    发布于 2019-10-16
    0 人赞同

    有一个库叫 NineOldAndroids 它允许你使用Honeycomb的动画库,一直到第一版。

    这意味着你可以用一个稍微不同的界面来定义左、右、translationX/Y。

    Here is how it works:

    ViewHelper.setTranslationX(view, 50f);
    

    你只需使用ViewHelper类的静态方法,传递视图和你想设置的任何值。

    brianmearns
    brianmearns
    发布于 2019-10-16
    0 人赞同

    我建议使用 setTranslationX setTranslationY 。我自己也是刚刚开始,但这些似乎是移动视图的最安全和最好的方式。我想这在很大程度上取决于你到底想做什么,但这对我来说对二维动画很有效。

    Chickenrice
    Chickenrice
    发布于 2019-10-16
    0 人赞同

    如果你使用HoneyComb Sdk(API Level 11),你可以尝试使用以下方法。

    view.setX(float x);
    

    参数x是这个视图的视觉x位置。

    view.setY(float y);
    

    参数y是该视图的视觉y位置。

    I hope it will be helpful to you. :)

    我在2.2 Froyo上工作,这些方法在它那里是不可用的。
    Orr
    Orr
    发布于 2019-10-16
    0 人赞同

    对于对所有API级别的支持,你可以使用 it like this:

    ViewPropertyAnimator.animate(view).translationYBy(-yourY).translationXBy(-yourX).setDuration(0);
        
    因为他想改变位置,而上述解决方案更好,不需要动画。
    mewa
    另外,翻译可能导致视图(部分)离开屏幕。
    Balaji.K
    Balaji.K
    发布于 2019-10-16
    0 人赞同

    设置该视图相对于其父级的左边位置。

    view.setLeft(int leftPosition);
    

    设置该视图相对于其父级的右边位置。

    view.setRight(int rightPosition);
    

    设置该视图相对于其父级的顶部位置。

    view.setTop(int topPosition);
    

    设置该视图相对于其父级的底部位置。

    view.setBottom(int bottomPositon);
    

    上述方法用于设置视图与其父级的相关位置。

    对不起,这些方法是不可用的。你能给我发送任何代码吗?
    "这个方法是用来被布局系统调用的,一般不应另行调用,因为这个属性可能随时被布局改变。"
    Alessandro Muzzi
    Alessandro Muzzi
    发布于 2019-10-16
    0 人赞同

    使用LayoutParams。 如果你使用的是LinearLayout,你必须导入android.widget.LinearLayout.LayoutParams,否则为你使用的布局导入适当版本的LayoutParams,否则会导致 类的转换异常 , then:

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

    注意:你也可以使用imageView.setLeft(int dim),但这不会设置组件的位置,它只会设置组件左边界的位置,其他部分将保持在相同的位置。

    那么,我们怎样才能在不影响原始视图的情况下将视图移动到特定的位置?
    我不确定我是否理解你的问题,因为如果你想移动一个视图,你会因为你移动它而改变它。总之,如果你想在另一个独立的视图上移动一个视图,你可能需要一个FrameLayout视图,然后,在它里面,你可以放置你的独立视图(显然,如果你想让它在你的主视图下移动,你必须把FrameLayout放在你的主视图之前)。
    glodos
    glodos
    发布于 2019-10-16
    0 人赞同

    使用 RelativeLayout ,将你的视图置于其中,从你的视图中获得 RelativeLayout.LayoutParams 对象,并按你的需要设置边距。然后在你的视图上调用 requestLayout() 。这是我知道的唯一方法。

    Ahmet B.
    Ahmet B.
    发布于 2019-10-16
    0 人赞同

    在Kotlin中,你可以像下面这样做。

    .animate() .x(50f) .y(100f) .duration = 500L
    Nguyen Tan Dat
    Nguyen Tan Dat
    发布于 2019-10-16
    0 人赞同

    我发现@Stefan Haustein与我的经验非常接近,但不确定100%。我的建议是。

  • 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 .
  • Braden Holt
    Braden Holt
    发布于 2019-10-16
    0 人赞同

    在定位方面需要记住的一点是,每个视图都有一个相对于其父视图的索引。因此,如果你有一个带有三个子视图的线性布局,子视图将各自有一个索引。在上面的例子中,0、1、2。

    这允许你在父级视图中的最后一个位置(或末尾)添加一个视图,具体做法如下。

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

    另外,你也可以使用类似以下的方法来替换一个视图。