HarmonyOS鸿蒙Next中请教一个动态修改组件高度,组件内子元素动画问题

HarmonyOS鸿蒙Next中请教一个动态修改组件高度,组件内子元素动画问题 下面组件代码,为啥只有展开的时候文本内容会随 Row 高度变化逐渐显示,隐藏的时候没有这个动画效果,文本直接就隐藏了

SDK:HarmonyOS 5.1.0 Release SDK

API版本:Version 18 Release

@Entry
@ComponentV2
struct TestPage {
  private content =
    '文本内容,文本内容,文本内容,文本内容,文本内容,文本内容'
  @Local status: boolean = true

  build() {
    Column() {
      Row() {
        Text(this.status ? '隐藏' : '展示')
          .margin({
            bottom: 10
          })
          .onClick(() => {
            this.status = !this.status
          })
      }
      .width('100%')

      Row() {
        Text(this.content)
          .width('100%')
      }
      .width('100%')
      .height(this.status ? 200 : 0)
      .clip(true)
      .alignItems(VerticalAlign.Top)
      .animation({
        duration: 1000,
        curve: Curve.EaseInOut
      })

    }
    .width('100%')
  }
}

更多关于HarmonyOS鸿蒙Next中请教一个动态修改组件高度,组件内子元素动画问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

因为你隐藏的时候高度直接设置为0,这样会导致组件的属性动画失效

可以这么写,加多一个显隐控制,且高度不置为0

@Entry
@ComponentV2
struct TestPage {
  private content =
    '文本内容,文本内容,文本内容,文本内容,文本内容,文本内容'
  @Local status: boolean = true

  build() {
    Column() {
      Row() {
        Text(this.status ? '隐藏' : '展示')
          .margin({
            bottom: 10
          })
          .onClick(() => {
            this.status = !this.status
          })
      }
      .width('100%')

      Row() {
        Text(this.content)
          .width('100%')
      }
      .width('100%')
      .height(this.status ? 200 : 'auto')
      .visibility(this.status ?Visibility.Visible:Visibility.None)
      .clip(true)
      .alignItems(VerticalAlign.Top)
      .animation({
        duration: 1000,
        curve: Curve.EaseInOut
      })

    }
    .width('100%')
  }
}
名称 说明
Hidden 隐藏,但参与布局进行占位。
Visible 显示。
None 隐藏,但不参与布局,不进行占位。

【官方文档——显隐控制】
【官方文档——属性动画】

更多关于HarmonyOS鸿蒙Next中请教一个动态修改组件高度,组件内子元素动画问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


组件的某些通用属性变化时,可以通过属性动画实现渐变过渡效果,提升用户体验。支持的属性包括widthheightbackgroundColoropacityscalerotatetranslate等。布局类改变宽高的动画,内容都是直接到终点状态,例如文字、Canvas的内容等,如果要内容跟随宽高变化,可以使用renderFit属性配置。

@Entry
@Component
struct RenderFitExample {
  @State width1: number = 100;
  @State height1: number = 30;
  flag: boolean = true;
  build() {
    Column() {
      Text("Hello")
        .width(this.width1)
        .height(this.height1)
        .borderWidth(1)
        .textAlign(TextAlign.Start)
        .renderFit(RenderFit.LEFT)// 设置LEFT的renderFit,动画过程中,动画的终态内容与组件保持左对齐
        .margin(20)
      Text("Hello")
        .width(this.width1)
        .height(this.height1)
        .textAlign(TextAlign.Center)
        .borderWidth(1)
        .renderFit(RenderFit.CENTER)// 设置CENTER的renderFit,动画过程中,动画的终态内容与组件保持中心对齐
        .margin(20)
      Button("animate")
        .onClick(() => {
          this.getUIContext()?.animateTo({ curve: Curve.Ease }, () => {
            if (this.flag) {
              this.width1 = 150;
              this.height1 = 50;
            } else {
              this.width1 = 100;
              this.height1 = 0;
            }
            this.flag = !this.flag;
          })
        })
    }.width("100%").height("100%").alignItems(HorizontalAlign.Center)
  }
}

cke_1108.png

cke_2269.png

尝试了一下, height 设置为 0 的时候不好使,如果设置成 1 就可以,为啥呢

在HarmonyOS Next中,使用animateTo方法实现动态修改组件高度时的子元素动画。通过状态变量控制组件高度,在animateTo动画闭包内更新状态,子元素会自动应用平滑过渡效果。关键代码示例:

@State height: number = 100
...
Button("点击动画")
  .onClick(() => {
    animateTo({ duration: 500 }, () => {
      this.height = this.height === 100 ? 200 : 100
    })
  })
...
Column() {
  // 子组件内容
}
.height(this.height)

动画参数可通过animateTooptions参数配置曲线与时长。

这是因为在折叠时,Row组件的高度从200变为0,同时clip属性为true,导致文本内容被直接裁剪隐藏,没有过渡动画。

问题在于:当高度变为0时,即使设置了animation,文本内容也会因为clip裁剪而立即消失,无法显示逐渐隐藏的动画效果。

解决方案:可以尝试以下两种方式:

  1. 使用opacity属性配合动画:
.height(this.status ? 200 : 0)
.opacity(this.status ? 1 : 0)
.clip(true)
.animation({
  duration: 1000,
  curve: Curve.EaseInOut
})
  1. 或者使用布局约束和margin/padding来实现折叠效果,避免高度直接变为0:
.height(this.status ? 200 : 1) // 最小高度保持1,避免完全裁剪
.clip(true)
.animation({
  duration: 1000,
  curve: Curve.EaseInOut
})

这样在折叠时文本内容会有一个渐隐的过渡效果,而不是直接消失。

回到顶部