HarmonyOS鸿蒙Next中Tabs的TabContent高度问题

HarmonyOS鸿蒙Next中Tabs的TabContent高度问题 看图片,我的TabContent里面放的是一个List,我发现下面有部分区域没有展示出来,来回修改了height什么的都不行。请教各位有知道怎么回事的吗?

关键代码如下:

主类代码:

build() {
    Column() {
      CustomNavView({navTitle: "告警管理", navStack: this.warningPageStack, showBackBtn: false, showBottomLine: true})
      Tabs({barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller}) {
        TabContent() {
          CurrentWarningListPage()
        }

        TabContent(){
          WarningRecordListPage()
        }
      }
      .vertical(false)
      .barMode(BarMode.Fixed)
      .barHeight(0)
      .animationDuration(300)
      .onChange((index: number) => {
        this.currentIndex = index;
        this.selectedIndex = index;
        if(index === 0){
          this.tabBgFlex = FlexAlign.Start;
        } else {
          this.tabBgFlex = FlexAlign.End;
        }
      })
      .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
        Logger.info(`----- currentOffset = ${event.currentOffset}   ==== targetOffset = ${event.targetOffset}`);
        Logger.info(`---------- index = ${index}  --------- targetIndex = ${targetIndex}`);
        if(index === targetIndex){
          return;
        }
        this.selectedIndex = targetIndex;
        if(targetIndex === 0){
          this.tabBgFlex = FlexAlign.Start;
        } else {
          this.tabBgFlex = FlexAlign.End;
        }
      })
      .width('100%')
      .height('auto')
      .backgroundColor(Color.Black)
    }
    .width('100%')
}

CurrentWarningListPage中代码如下

build() {
    Refresh({refreshing: $$this.refreshing, builder: this.refreshHeader()}){
      List(){
        ForEach(this.dataArr, (item: number) => {
          ListItem(){
            WarningListCell()
          }
        })

        ListItem(){
          this.refreshFooter()
        }
      }
        .onScrollIndex((start: number, end: number) => {
          if(end >= this.dataArr.length - 1){
          }
        })
        .scrollBar(BarState.Off)
        .edgeEffect(EdgeEffect.Spring, {alwaysEnabled: true})
    }
      .width('100%')
      .height('100%')
      .onOffsetChange((offset: number) => {
        this.refreshOffset = offset;
      })
      .onStateChange((state: RefreshStatus) => {
        this.refreshState = state;
      })
      .onRefreshing(() => {
        setTimeout(() => {
          this.refreshing = false;
        }, 5000)
      })
  }

可能是什么问题呢


更多关于HarmonyOS鸿蒙Next中Tabs的TabContent高度问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

11 回复

开发者你好:

【背景知识】

  • height:用于设置组件自身的高度,缺省时使用元素自身内容需要的高度。若子组件的高大于父组件的高,则会画出父组件的范围。
  • margin:用于设置组件的外边距属性。
  • layoutWeight:用于设置组件的布局权重,使组件在父容器(Row/Column/Flex)的主轴方向按照权重分配尺寸。父容器尺寸确定时,不设置layoutWeight属性或者layoutWeight属性生效值为0的元素优先占位,这些元素占位后在主轴留下的空间称为主轴剩余空间。设置了layoutWeight属性且layoutWeight属性生效值大于0的子元素会从主轴剩余空间中按照各自所设置的权重占比分配尺寸,分配时会忽略元素本身的尺寸设置。
  • Flex组件:是以弹性方式布局子组件的容器组件,提供更加有效的方式对容器内的子元素进行排列、对齐和分配剩余空间。

【问题定位】

  1. 首先观察到List组件未设置高度,根据height属性说明:height缺省时使用元素自身内容需要的高度。所以List组件高度为子组件之和。
  2. 然后根据List的尺寸约束示例可以看到,当子组件主轴方向总尺寸超过List父组件尺寸时,List主轴方向尺寸适应List的父组件尺寸,所以List组件高度为屏幕高度。
  3. 再然后根据layoutWeight布局说明:不设置layoutWeight属性或者layoutWeight属性生效值为0的元素优先占位。所以List组件会在剩余空间内占位,导致List组件被下压,下压后List组件就有部分区域会超过当前屏幕高度,所以造成List展示不全现象。
  4. 最后可以利用ArkUI Inspector可以看到List组件超出屏幕范围。

【分析结论】

当List组件上面有其他元素并且List子组件高度之和超出屏幕范围时,会导致List组件被下压,造成List展示不全的问题。

【方案一】给List组件设置高度

设置固定高度以后List组件就会在限定的范围内滑动,比如设置300vp后List组件就在300vp内进行滑动:

List() {
  // ...省略内容
}
.height(300)

注意:上文300vp只是演示效果,具体数值看业务需要;若height值超过剩余屏幕高度,比如1000vp,则设置无效

或者利用calc特性计算List组件在主轴方向剩余高度:

List() {
  // 省略内容
}
.height('calc(100% - 200vp)')

注意:calc公式中200vp的高度为List上面Text组件的高度。

【方案二】给List组件设置layoutWeight属性

在主轴剩余空间内,设置了layoutWeight属性的子元素与兄弟元素会在主轴方向按照权重分配尺寸。给List组件设置layoutWeight属性即可:

List() {
  // 省略内容
}
.layoutWeight(1)

注意:以上场景Text组件后面只有List组件,故layoutWeight设置无论何值都行,不过一般都会设置成layoutWeight(1)。

【方案三】给List组件设置margin属性

利用ArkUI Inspector可以看到List组件超出屏幕范围,超出的距离刚好是上面Text组件占据高度200vp。而margin属性就是用于设置组件的外边距,所以给List组件设置margin底部200vp即可:

List() {
  // 省略内容
}
.margin({ bottom: 200 })

【方案四】使用Flex布局

Flex组件提供更加有效的方式对容器中的子元素进行排列、对齐和分配剩余空间,设置FlexWrap.NoWrap即可让子元素尽可能约束在容器内。

build() {
  Flex({
    wrap: FlexWrap.NoWrap,
    alignItems: ItemAlign.Center,
    direction: FlexDirection.Column
  }) {
    Text('我是一级容器Column的Text组件')

    List() {
      // 省略内容
    }
  }
  .height('100%')
  .width('100%')
}

【总结】

List组件由于其滚动特性一般不会设置其高度,而当List在父容器内有其他兄弟节点处于上方并且List组件高度超出屏幕范围时,就会造成List展示不全问题,本文提供四种方案进行解决,四种方案对比如下,开发者可以自行根据对比进行选择:

方案 原理 说明
设置height 约束List组件的高度 设置固定高度局限较多,应用场景较少;利用calc计算需要获悉上面节点的高度
设置layoutWeight 在主轴剩余空间内分配List尺寸 应用场景最多,使用最方便,推荐使用
设置margin 设置List组件的外边距 需要获悉上面节点的高度
使用Flex布局 利用弹性布局方式 会更改页面布局,需要根据实际情况选用

【常见FAQ】

Q:List组件被父容器组件包裹,父容器组件有同级组件时,单纯给List设置layoutWeight不生效该如何解决?

A:这是由于没有给List的父组件设置高度所致,给父容器也加上layoutWeight即可。

更多关于HarmonyOS鸿蒙Next中Tabs的TabContent高度问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


不过,经过尝试,给List组件设置layoutWeight并没有作用。最终我是通过给父组件设置的padding解决的。和给List设置margin一个道理,

试下这种方式

@ComponentV2
struct cs002{
  build() {
    Tabs(){
      TabContent(){
        Column(){
          //放置自定义组件.......
        }
        .height('100%')
        .width('100%')
      }
      .height('100%')
      .width('100%')
    }
    .height('100%')
    .width('100%')
  }
}

试了,不行。

可以加上一个padding可以显示的

是的,你看我代码,我注释了pandding, 加上padding的确可以正常展示,但我觉的这不是根本解决办法,或者没有理解问题的根源。所以想看看有没有其他的解决办法,

.height(‘auto’) 这一行改成 .layoutWeight(1) 试试,

有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html

试过的,不行,

在HarmonyOS Next中,Tabs组件的TabContent高度默认会填充剩余空间。若需自定义高度,可在TabContent布局属性中设置具体高度值,或用百分比布局。若内容超出,建议结合Scroll组件使用。可通过measureMode属性控制测量模式,如设置为EXACTLY来指定精确高度。注意父容器约束可能影响最终效果。

从代码和截图来看,TabContent高度问题可能是由于布局约束导致的。建议检查以下几点:

  1. 主Column容器没有设置明确高度,导致Tabs高度计算异常。可以尝试为Column添加.height('100%')属性。

  2. Tabs组件设置了.height('auto'),这在嵌套布局中可能导致高度计算不准确,建议改为.height('100%')或固定高度值。

  3. CurrentWarningListPage中的List虽然设置了.height('100%'),但需要确保父容器(TabContent)有明确的高度约束。

  4. 可以尝试在Tabs外层添加一个固定高度的容器,或者使用Flex布局的flexGrow属性来分配剩余空间。

简单修改方案:

Column() {
  CustomNavView(...)
  Tabs(...) {
    TabContent() {
      CurrentWarningListPage()
    }
    ...
  }
  .height('100%')
  .flexGrow(1)  // 添加这行
}
.width('100%')
.height('100%')  // 确保Column有明确高度

这种问题通常是由于嵌套布局中高度约束不完整导致的,确保每个容器都有明确的高度约束是关键。

回到顶部