HarmonyOS 如何实现一个flex的动画,实现淡入淡出的效果?

page 布局里有一个flex 组件,该组件响应手势的上滑和下滑事件, 上滑时,组件从父布局底部出现,滑动到正确位置,下滑时相反,父布局的顶部出现,滑动到正确位置

阅读 473
1 个回答

根据转场动画:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-enter-exit-transition-V5

import { curves } from '@kit.ArkUI';

const effect: object =
  TransitionEffect.OPACITY .animation({ curve: curves.springMotion(0.6, 0.8) })// 创建了透明度转场效果,这里没有调用animation接口,会跟随animateTo的动画参数
    // 通过combine方法,添加缩放转场效果,并指定了springMotion(0.6, 1.2)曲线
    // .combine(TransitionEffect.scale({ x: 0, y: 0 }).animation({ curve: curves.springMotion(0.6, 1.2) }))
    // 添加旋转转场效果,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion(0.6, 1.2)
    // 添加平移转场效果,动画参数会跟随其之上带animation的TransitionEffect,也就是springMotion(0.6, 1.2)
    .combine(TransitionEffect.translate({ y: '100%'}).animation({curve: curves.springMotion()}))
// 添加move转场效果,并指定了springMotion曲线
// .combine(TransitionEffect.move(TransitionEdge.END))
// 添加非对称的转场效果,由于这里没有设置animation,会跟随上面的TransitionEffect的animation效果,也就是springMotion
// .combine(TransitionEffect.asymmetric(TransitionEffect.scale({ x: 0, y: 0 }), TransitionEffect.rotate({ angle: 90 })));
// xxx.ets
@Entry
@Component
struct ModalTransitionExample {
  @State isShow:boolean = false
  @State isShow2:boolean = false
  @State currentOffsetY:number = 0;
  // 出现时会是所有转场效果的出现效果叠加,消失时会是所有消失转场效果的叠加
  // 用于说明各个effect跟随的动画参数

  @Builder myBuilder2() {
    Column() {
      Button("close modal 2")
        .margin(10)
        .fontSize(20)
    }
    .onTouch((event?: TouchEvent) => {
      if (event === undefined) {
        return;
      }
      console.log('event.type---'+event.type);
      switch (event.type) {
        case TouchType.Down:
          this.currentOffsetY = event.touches[0].y;
          break;
        case TouchType.Move:
          let isUpPull = event.touches[0].y - this.currentOffsetY> 50;
          if(isUpPull){this.isShow2 = false;}
          break;
        case TouchType.Cancel:
          break;
        case TouchType.Up:
          break;
      }
    })

    .width('100%')
    .height('100%')
  }

  @Builder myBuilder() {
    Flex({direction: FlexDirection.Column}) {
      Column(){
        Text("上滑跳 transition modal 2")
          .margin(10)
          .fontSize(20)

      }
      Column(){
        Text("下滑回 modal 1")
          .margin(10)
          .fontSize(20)
      }
    }
    .onTouch((event?: TouchEvent) => {
      if (event === undefined) {
        return;
      }
      console.log('event.type---'+event.type);
      switch (event.type) {
        case TouchType.Down:
          this.currentOffsetY = event.touches[0].y;
          break;
        case TouchType.Move:
          let isDownPull = this.currentOffsetY - event.touches[0].y > 50;
          console.log('isDownPull----'+isDownPull)
          console.log('event.touches[0].y----'+event.touches[0].y,'this.currentOffsetY--'+this.currentOffsetY)
          if (isDownPull) {
            this.isShow2 = true;
          }
          let isUpPull = event.touches[0].y - this.currentOffsetY> 50;
          if(isUpPull){this.isShow = false;}
          break;
        case TouchType.Cancel:
          break;
        case TouchType.Up:
          break;
      }
    })
    // .bindContentCover(this.isShow2, this.myBuilder2(), {
    // modalTransition: ModalTransition.DEFAULT,
    // backgroundColor: Color.Gray,
    // onWillAppear: () => {console.log("BindContentCover onWillAppear.")},
    // onAppear: () => {console.log("BindContentCover onAppear.")},
    // onWillDisappear: () => {console.log("BindContentCover onWillDisappear.")},
    // onDisappear: () => {console.log("BindContentCover onDisappear.")}
    // })
    .width('100%')
    .height('100%')
  }

  @Builder myBuilder1(){
    Column() {
      Column(){
        Text("transition modal 1")
          .fontSize(20)
          .margin(10)

      }
    }
    .onTouch((event?: TouchEvent) => {
      if (event === undefined) {
        return;
      }
      console.log('event.type---'+event.type);
      switch (event.type) {
        case TouchType.Down:
          this.currentOffsetY = event.touches[0].y;
          break;
        case TouchType.Move:
          let isDownPull = this.currentOffsetY - event.touches[0].y > 50;
          console.log('isDownPull----'+isDownPull)
          console.log('event.touches[0].y----'+event.touches[0].y,'this.currentOffsetY--'+this.currentOffsetY)
          if (isDownPull) {
            this.isShow = true;
          }
          break;
        case TouchType.Cancel:
          break;
        case TouchType.Up:
          break;
      }
    })
    .justifyContent(FlexAlign.Center)
    .backgroundColor(Color.Blue)
    .width('100%')
    .height('100%')
  }


  build() {
    Column(){
      Text('我是头部').width('100%').height('10%').backgroundColor(Color.Red);
      Stack(){

        Column(){
          this.myBuilder1();
        }.width('100%').height('100%')
        if(this.isShow){
          Column(){
            this.myBuilder();
          }
          .backgroundColor(Color.Pink)
          .transition(effect).width('100%').height('100%')
        }
        if(this.isShow2){
          Column(){
            this.myBuilder2();
          }
          .backgroundColor(Color.Orange)
          .transition(effect)
          .width('100%').height('100%')
        }
      }
    }
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进