之前理解的不深,今天遇到一个坑,收获了一些更深的理解。

需求是这样:一个相对布局的Panel,里面有个ImageView,界面其他地方有几个按钮,按下去后需要动态地改变这个ImageView的位置。

按照往常的理解,按钮事件得到触发后,无非这样操作就可以了嘛:

node:getLayoutParameter():setMargin({ left = 10, right = 0, top = 0, bottom = 0 })

可是,这句话居然不起作用!把这句话移到UI创建时的那一堆代码里,却又起作用了!好奇怪,于是我就掉进这个坑里了。

后来也不知道怎么的脑门灵感一闪,在Layout类里看到了一个requestDoLayout()方法,于是将代码改成这样,终于生效了:

node:getLayoutParameter():setMargin({ left = 10, right = 0, top = 0, bottom = 0 })
node:getParent():requestDoLayout()

我的理解是,在一个相对定位的Panel里,如果是在UI创建期间(也即第一帧的时候),无论怎么搞这个Panel里面的子节点,它们都会生效,完全不需要手动执行requestDoLayout()方法去请求Panel重新定位,因为这个时候Panel是在OnEnter状态,内部是dirty状态。而当UI已经创建好了之后(也即第一帧完成了),这个时候要再去更改Panel里的子节点位置,Panel感知不到变化
,内部不是dirty状态,不会重新对子节点定位,所以需要手工地请求一次requestDoLayout(),让Panel对子节点新的设置生效。

一个有趣的实验是这样:创建一个Panel,相对定位,创建一个ImageView子节点node,左对齐、上对齐(只要不是居中就行,因为设置为居中后就固定死不能动了),创建好之后,随便找一个按钮A做个事件,这么写:

node:setPositionX(100)

点击按钮触发事件,你会发现node的位置发生变化了。然后把再加一个按钮B,触发事件里这么写:

node:getParent():requestDoLayout()

先点按钮A,node位置变了,再点按钮B,会发现node又跑回原位置了,哈哈。

总结:要在相对定位的Panel里用程序动态改变位置,避免使用setPosition(),而依然要使用LayoutParameter的setMargin()方法,只不过,还要再对Panel做一下requestDoLayout()调用,通知Panel去重新梳理一遍子节点


洪亮
697 声望64 粉丝

引用和评论

0 条评论