HarmonyOS 鸿蒙Next Position的用法,文档描述太不清晰了,用起来就靠猜。

发布于 1周前 作者 yuanlaile 来自 鸿蒙OS

HarmonyOS 鸿蒙Next Position的用法,文档描述太不清晰了,用起来就靠猜。

看文档描述:

绝对定位,设置子元素左上角相对于父容器左上角偏移位置。在布局容器中,设置该属性不参与父容器布局,即不占位,仅在绘制时进行位置调整。

适用于置顶显示、悬浮按钮等组件在父容器中位置固定的场景。

不支持在宽高为零的布局容器上设置。

当父容器为RelativeContainer时不生效。

有能知道源码能清晰的描述下问题吗?

比如不参与父容器布局,即不占位,是不是父布局计算位置的时候,跟这个控件没有关系,相当于没有这个view?不占位指的是父布局计算大小的时候不占位还是指父布局设置子控件位置的不占位?这个根本就没有说这个事呀?

如果位置不变,但是我看点击事件是按设置pisition()之后位置响应的,这个有计算点击事件位置遍历的时候有加偏移量的处理吗?这个文档也没有说过。

为什么只在绘制的时候位置调整呢?这样的话就为了省了一次计算大小和确定位置的计算?还是父布局计算和设置位置的时候根本就没有这个控件参与计算呢?

不参与计算,是不是控件使用pisition()和不使用pisition()的变化的时候,需要重新加载控件,这个的话,重新加载控件会有缓存处理吗?

经过测试,position()可以偏移出父布局的范围,在父布局之外显示?这个是不是表示使用position(),view的位置就不受父布局,只有宽高受父布局的约束?

文档描述这个功能太简单了,根本就没有把这个position()功能说的太简单了,这些问题不描述清楚,我们也看不到源码,只能猜???

9 回复

这是个好问题,但要说清楚确实比较复杂:)

一、组件布局主要与位置和尺寸两方面相关,两方面虽有关联但是属于分开的属性/参数;两方面属性的配置及行为方式都和父子组件间有无依赖关系有密切关系;

二、position属性表面上只和位置设置相关,其实也间接影响尺寸(后面会讲到);UI中全部组件的位置都是相对的——相对于屏幕/父组件或以对齐属性相对于某个其它组件或屏幕边缘;position虽然叫做绝对定位,其实还是相对的,相对于父组件或屏幕的左上角位置,除最外层容器这其实是一种子对父的依赖关系;而父组件布局不指定位置属性时默认是对子组件依赖的,即自适应子组件位置;这样就会出现循环依赖的问题;因此对于指定position的组件,估计布局为了避免循环依赖问题限制了带position的组件对父组件的布局影响,即文档中所述的不参与父容器布局;而且这个影响不只是位置,也和尺寸的计算有关系;

但这个不参与可能也有不同情况,如果父组件只有这一个子组件且自适应子组件,这个不参与就有问号了;如果有其它子组件则父组件可根据其它子组件来确定位置,把带position的子组件不考虑在父组件定位时的计算之内可以理解;如果是独子呢,估计就得看爷组件的对齐规则或爷组件(或屏幕)的位置来确定默认位置作为初始定位参照,父组件则按默认位置结合位置属性来定位,子组件则相对默认位置用postion相对定位;这个默认位置则成为计算时采用的一个锚点;

三、另一方面,布局中的尺寸问题,依然要考虑依赖关系的影响;如果父组件自适应子组件则父组件默认是要包裹所有子组件大小的,而带position的子组件也可能引起循环依赖问题,比如子组件宽度按父组件百分比计,带上position后横向或纵向可能超出父组件边界,则父组件需要增加宽高以包裹此子组件,然后子组件按百分比再变大,如此循环变成不可预计的尺寸;因此将此子组件排除在父组件尺寸计算之外也是必要的限制;

如果父组件不依赖子组件尺寸,子组件尺寸是可能超出父组件范围的,加上position的指定甚至可实现将子组件放在屏幕外达到隐藏的效果。如果父组件自适应包裹子组件,则对于不带position的子组件,父组件是会在子组件确定尺寸和位置后自动调整自身尺寸实现包裹的效果,那怕最终父组件尺寸是超出屏幕范围,逻辑上是没问题的;

另一种循环依赖场景是父组件自适应子组件,而子组件以百分比指定尺寸,则可能出现最终无限大或为0的两种结果;问题的根源是没有一个固定参照尺寸;而正常的用法是子依赖父一层层直到依赖屏幕大小实现可靠的尺寸控制;

与position类似的定位属性offset其实效果是近似的;文档中同样说明不影响父容器布局;

==》理解了位置和尺寸两方面在布局中因依赖关系可能造成的问题后再回顾position可能对这两方面的影响就比较清晰了;Tiger提到position是优先级最低的也许就是因为这个属性造成麻烦的可能性是最大的。

另外UI系统布局的最终结果应该是将各级组件的位置和尺寸计算好后变成组件自身的属性值,而这些值再用于绘制则成为确定的绘制参数;至于动态更新position则会触发布局计算重新确定这些属性值,也就影响后续绘制的参数变化成为UI刷新的后台机制;

由于相关属性不少,依赖关系也可能在位置和尺寸上不一致,所以组合情况也会很多,但大体有这个思路可自行分析不同组合场景下的实际效果。文档也确实难以在小篇幅里说清楚个中细节,但理解了其中可能存在的矛盾和问题就能理解文档给出的结论。

题外话:position这个属性还是很有用的,有了它可以不使用Canvax/XComponent就能在正常组件UI环境中实现自制动画甚至简单游戏的功能;

谢谢您了,辛苦。 看了您的分享,我得到一个结论,其实导致这个根本原因还是所有的组件宽高支持百分比导致的。因为百分比不是一个确定的值,任何一个子控件或者是父控件都可能影响百分比的值;这么说这个坑有点大,需要太多的东西去填。其实我现在觉得还是Android那套不错,因为基本每个控件都是大小固定的,或者是自适应的,只有约束布局是支持百分比的,而且还只是内部支持,这样的话,基本就没有所谓的无限循环问题。又有点感觉这个问题就像是一个图论问题,只要能做的有向无环图就可以了,因为百分比的问题,就是没有中断间隔,所有很难得到有向无环图,更可能得到一个有向环图,这样就出现了无限循环的可能了;因为像Android其实可以看成小部分控件是百分比的,而且百分比不是层层嵌套的,这样的就对无限循环造成了中断间隔。

说句实话,我没有体会到所有控件都支持百分比所带来的好处,可能是我对鸿蒙的UI理解不深;反倒是觉得因此所有的组件支持自适应的实现不了,感觉跟您说的这个原因也是有关系,但是我们开发应用为了这个需要做更多的处理,有时候还达不到想要的效果。在系统应用里面,可能就是图片,其他的用百分比的真的不多。

还有,其实我觉得有用,好用 和 用对,用好还是区别很大的;有用,好用确实省事,但是无法用好,无法用对,坑更大;

所有复杂的问题,根本就不可能通过一个简单的文档去讲的清楚;如果使用者不清楚,一个大家有疑惑的,总是出问题的功能,不知道多少人会觉得这个好用?

当然如此,就跟武功一样,没有天天练、天天揣摩,想成高手也难; 灵活与复杂是相伴而生的,变量越多越灵活,却也越复杂;最后可能作者也不清楚所有组合会出什么状况,可以给个推荐模板,但用的人会有千万种想法和尝试,只能见招拆招了:) 布局中用百分比可能是为了适配不同屏幕的一种尝试;但所有相对最后要归结到一个可参照物(值)上整个才能成立,自适应是从内向外推导;百分比是从外向内推导,两者虽然都是相对设置的推算但方向不同;前者需要内层某个节点有可确定的位置及尺寸;后者则以屏幕左上角和宽高为最终依托,各有优劣,看应用场景选择吧。

绝对定位,确定子组件相对父组件的位置。当父容器为Row/Column/Flex时,设置position的子组件不占位。 Position类型基于父组件左上角确定位置;Edges类型基于父组件四边确定位置,top/left/right/bottom分别为组件各边距离父组件相应边的边距,通过边距来确定组件相对于父组件的位置;LocalizedEdges类型基于父组件四边确定位置,支持镜像模式。 适用于置顶显示、悬浮按钮等组件在父容器中位置固定的场景。 不支持在宽高为零的布局容器上设置。 当父容器为RelativeContainer, 且子组件设置了alignRules属性, 则子组件的position属性不生效。 position是最最后生效的。

现在有一个问题是Position可以出父控件的范围。 其实就是最后显示的时候,父控件对Position是约束极小,其实基本情况下,子控件是显示是不能出父控件的范围的。 还有就是点击事件也不知道命中的原理,如果不占位,点击事件的时候,这个是按最后显示的位置算?不占位的话,怎么会命中点击事件呢?在父控件中没有位置,计算的点击事件的时候就有了? 出了父控件的范围还能显示,这个时候父控件范围之外的还能命中点击事件吗?

其实Position 这个说的简单的原因在于设置position位置的时候,可以显示在父控件之外,这个就问题很多了。 或者换一个问法,父控件对于设置的Position的子控件的约束是什么?我现在的理解是设置Position后,好像父控件对其约束极小,比较确定是有大小的约束了。

我对这个疑问是不少的,但是文档就几句话,这些根本就没有说。 其实相对的还有一个offset的属性。 其实刚刚您说了 Edges 和 LocalizedEdges,因为这个是12才有,之前我没有看到,相比这个,Position有一个很大的区别就是如果某个组件需要取消Position,一般得重新加载这个组件才行。相比之下Edges 和 LocalizedEdges,就没有这个。

可以理解为层叠到父组件的上图层?然后可以通过x,y基于父组件的左上角设置位置吧,不会占用原来的位置

不能确定,说在父组件上层,还是有父组件的约束的;说不在上层,又能出父组件的范围,这个我也不知道,只是我测试看到的效果,所有我才说文档描述不清晰或者是太简单了。 都是猜测,不一定对,所以需要鸿蒙的人来回答下了,毕竟我们也看不到源码。

HarmonyOS 鸿蒙Next中Position的用法确实在文档中描述得不够详细,但可以通过以下理解来明确其使用方式:

Position属性主要用于绝对定位,它确定子组件相对于父组件左上角的位置。设置该属性后,子组件将不参与父容器的布局计算,即不占位,仅在绘制时进行位置调整。这适用于需要固定位置的组件,如置顶显示或悬浮按钮。

使用时,可以通过.position({x:数值,y:数值})来设置偏移量,其中x和y分别代表横向和纵向的偏移距离。需要注意的是,绝对定位后的组件可能会覆盖其他组件,因此可以通过.zIndex()来调整组件的层级关系。

此外,Position属性虽然主要影响位置,但也可能间接影响尺寸计算。在设置时,需确保不会引发布局循环依赖或尺寸计算错误的问题。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部