问题描述
学习中在写界面的时候,用到了一个叫RelativeContainer的组件,楼主本来想实现如图所示的界面
但是楼主在写代码的时候,如下方代码、所示,发现RelativeContainer这个空间,如果不给定确切的宽高,默认是铺满,展示的跟原本预期的不同
如下方代码,是按照下方这种布局思路来的
--Colum //竖向线性布局
|--RelativeContainer //个人任务, 工作任务选框布局
|--个人任务及单选框布局
|--工作任务单选框布局
|--Text// 新建任务文案
代码如下:
@Extend(Text) function myRadioDescribeText1(){
.fontColor($r("app.color.radio_describe"))
.fontSize($r("app.float.text_H5"))
}
@Entry
@Component
struct test{
build() {
Column(){
// 相对布局控件, 代码里没有对这个相对布局设置宽高
RelativeContainer(){
// 个人任务的单选框
Radio({value : "个人任务", group : "task_type"})
.id("private_radio")
.checked(true)
.alignRules(
{start : {anchor : "__container__", align : HorizontalAlign.Start},
top : {anchor : "__container__", align : VerticalAlign.Top},
}
)
Text($r("app.string.add_task_type_private"))
.myRadioDescribeText1()
.alignRules({
start : {anchor : "private_radio", align : HorizontalAlign.End},
center : {anchor : "private_radio", align : VerticalAlign.Center}
}
).offset({x : 10})
Text($r("app.string.add_task_type_work"))
.id("work_radio")
.myRadioDescribeText1()
.alignRules({
end : {anchor : "__container__", align : HorizontalAlign.End},
center : {anchor : "private_radio", align : VerticalAlign.Center}
})
.offset({x : -10})
// 工作任务的单选框
Radio({value : "工作任务", group : "task_type"})
.checked(false)
.alignRules(
{end : {anchor : "work_radio", align : HorizontalAlign.Start},
center : {anchor : "work_radio", align : VerticalAlign.Center}
}
).offset({x : -10})
}
.border({width : 3, color : Color.Blue})
// 新建任务,文本框
Text($r("app.string.add_task_page_title"))
.id("page_title")
.fontSize($r("app.float.title_H5"))
.fontColor($r("app.color.title_color2"))
.fontWeight(FontWeight.Bold)
}
}
}
展示:
因为展示不如预期,所以楼主对RelativeContainer部分加了蓝色边框。图上效果很明显,RelativeContainer 占满全屏幕了,显然不符合预期的。
于是楼主看了网上的帖子,也问了AI, 在RelativeContainer后面指定宽度为100%, 高度为 auto。发现还是不好用。
RelativeContainer(){
// 这里即使只有一个Text控件。他也是占满全屏
}
.width('100%').height('auto') //不好使!照样是铺满全屏
这是网上看来的答案,结果并没有解决,所谓的自适应效果根本没有!绝知此事要躬行啊!这么重要的控件连自适应能力都没有的话, 不太可能啊?
RelativeContainer的自适应在什么时候奏效?
这里的自适应就是当写如上方代码, 将width或者height给为auto的时候,什么时候是奏效的。
楼主经过测试得到一个答案是:.width('100%').height('auto')这种代码给RelativeContainer设置, 在某些情况下是奏效的, 某些情况下却又不会奏效。
比如您设置了纵向高度为自适应,到底真实情况下,究竟是不是自适应,得看子元素alignRules是怎么设置的!
里如下面的代码, 楼主测得,在RelativeContainer设置为高度 auto 的时候
子控件alignRules 中,只设置横向锚点,来确定其横向应该在什么位置, 此时,RelativeContainer可以满足自适应要求。
子控件alignRules中, 但凡设置了纵向的锚点,而且这个锚点正好是父布局RelativeContainer的一个边,此时RelativeContainer的 height auto特点原地消失!RelativeContainer直接撑开全屏了就!(比较过分)
RelativeContainer(){
Radio({value : "个人任务", group : "task_type"})
.width(20).height(20)
.id("private_radio")
.checked(true)
.alignRules(
{start : {anchor : "__container__", align : HorizontalAlign.Start},
// top : {anchor : "__container__", align : VerticalAlign.Top},
}
)
}
.width('100%').height('auto')
为了方便理解,现象如下图所示:
解
将RelativeContainer的高度设置为 "auto"
将RelativeContainer的所有子控件的相对位置锚点,纵向上的那些锚点, top, bottom, center, 不要与父布局的任何边边, 任何中间点建立锚点关系。
修改完后的代码如下:
@Extend(Text) function myRadioDescribeText1(){
.fontColor($r("app.color.radio_describe"))
.fontSize($r("app.float.text_H5"))
}
@Entry
@Component
struct test{
build() {
Column(){
RelativeContainer(){
Radio({value : "个人任务", group : "task_type"})
.width(20).height(20)
.id("private_radio")
.checked(true)
.alignRules(
{start : {anchor : "__container__", align : HorizontalAlign.Start}}
// bugFix 删除 top : {anchor : "__container__", align : VerticalAlign.Top},
// 因为楼主的其余子控件相对位置都是根据这个空间来进行标锚的,所以其余子控件不用改,只改
// 这个就好了
)
Text($r("app.string.add_task_type_private"))
.myRadioDescribeText1()
.alignRules({
start : {anchor : "private_radio", align : HorizontalAlign.End},
center : {anchor : "private_radio", align : VerticalAlign.Center}
}
).offset({x : 10})
//
Text($r('app.string.add_task_type_work'))
.id("work_radio")
.myRadioDescribeText1()
.alignRules({
end : {anchor : "__container__", align : HorizontalAlign.End},
center : {anchor : "private_radio", align : VerticalAlign.Center}
})
.offset({x : -10})
Radio({value : "工作任务", group : "task_type"})
.checked(false)
.alignRules(
{end : {anchor : "work_radio", align : HorizontalAlign.Start},
center : {anchor : "work_radio", align : VerticalAlign.Center}
}
).offset({x : -10})
}
.border({width : 3, color : Color.Blue})
.width("100%").height("auto") // bugFix 对相对布局容器高度指定为 auto
Text($r("app.string.add_task_page_title"))
.id("page_title")
.fontSize($r("app.float.title_H5"))
.fontColor($r("app.color.title_color2"))
.fontWeight(FontWeight.Bold)
}
}
}
关于 RelativeContainer 的理解与扩展
为了方便记忆,我们不妨认为这个RelativeContainer的 宽高指定auto的情况下,应该是,只要不较真设置相应方向的锚点, 就会自适应, 一旦程序员较真设置了相应方向的锚点关系, 并且这个锚点的边还是父布局RelativeContainer的某些边边,那么,就得计算测量了。您又没给确切的宽高,那人家只能默认撑开父布局的大小。
我们可以将每个锚点简单的理解为,一个橡皮筋。这个与Android上的约束布局--ConstraintLayout极其相似。
小小扩展
楼主的整篇文章,是建立在读者已经会使用RelativeContainer的基础上来的,或者来说,最低也会会照葫芦画瓢的程度来写案例的水平之上。
对于RelativeContainer,初学者开始学的话,可以通过看视频或者看官方文档进行学习。
但是楼主读文档时仍然觉得晦涩。看这些文章之前, 我们不妨先建立一个拟物化的想象。就是我们可以在不知道这文章里提出的所有概念前, 拟物一个场景, 就是橡皮筋拉扯,将物体固定在空间中的场景,然后再带入,看代码看文章。或许就更容易理解其中的思想。
指南中 RelativeContainer 的解释:
API中 RelativeContainer 的解释:
如果按照弹簧思想来理解今天遇到的问题,我们就不难解释了。就是高度上设置了 auto , 但是,一旦子控件设置竖向上锚点,正好是父布局 RelativeContainer 自己的边, 那么,就意味着这个“边”必须要“存在了”, 并且还要有个确切的距离,来约束被链接上的物体。既然存在,那这个位置到底离物体多远呢?用户没有给,只给了个auto。如果还按照auto来,那么之后的占比权重怎么计算?所以这个距离应是确定的。为父布局。
总结
AI问答得到的答案暂时解决不了一些看似刁钻实则普通的问题,要全面替代程序员,有段路程要走。
RelativeContainer 可以为宽高设置为 auto 来实现自适应宽度或者高度。但是这个自适应,会因为子控件的alignRules设置方式而被打破。子控件没有面向RelativeContainer边上的锚点时((left, middel, right)横向, (top, center, bottom)纵向), 则其对应的方向就会自适应。一旦有了锚点则相关方向默认铺满。
领取专属 10元无门槛券
私享最新 技术干货