案例:自定义下拉刷新动画(ArkTS)

本文介绍了如何在Codelab中通过属性动画为组件设置动态效果,如自定义下拉刷新组件的动画设置,包括动画时长、速率、延时等因素。展示了如何在实际项目中应用这些技术,提升用户体验。
摘要由CSDN通过智能技术生成

介绍

在这里插入图片描述

本篇Codelab主要介绍组件动画animation属性设置。当组件的某些通用属性变化时,可以通过属性动画实现渐变效果,提升用户体验。

本Codelab使用的display接口处于mock阶段,在预览器上使用会显示白屏现象,可选择在真机或模拟器上运行。

相关概念

  • 属性动画:组件的某些通用属性变化时,可以通过属性动画实现渐变效果,提升用户体验。支持的属性包括width、height、backgroundColor、opacity、scale、rotate、translate等。案例中自定义头部组件的属性动画设置主要涉及duration(动画时长)、tempo(动画速率)、delay(动画延时)、curve(动画曲线)、palyMode(动画模式)和iterations(动画播放次数)。

完整示例

gitee源码地址

源码下载

自定义下拉刷新动画(ArkTS).zip

代码结构解读

本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在源码下载或gitee中提供。

├──entry/src/main/ets                      // 代码区           
│  ├──common
│  │  ├──constants                     
│  │  │  ├──CommonConstants.ets            // 公共常量类
│  │  │  └──RefreshConstants.ets           // 下拉刷新常量类
│  │  └──utils                 
│  │     ├──DimensionUtil.ets              // 屏幕适配工具类
│  │     └──GlobalContext.ets              // 全局上下文工具类
│  ├──entryability
│  │  └──EntryAbility.ets                  // 程序入口类
│  ├──pages
│  │  ├──FileManagerIndex.ets              // 文件管理Tab页
│  │  └──TabIndex.ets                      // Tab管理页
│  ├──view
│  │  ├──RefreshAnimHeader.ets             // 动画刷新组件
│  │  ├──RefreshComponent.ets              // 下拉刷新组件
│  │  └──RefreshDefaultHeader.ets          // 默认刷新组件
│  └──viewmodel
│     ├──AnimationModel.ets                // 动画封装类
│     └──CardModel.ets                     // 页签封装类
└──entry/src/main/resources                // 资源文件目录

自定义下拉组件

自定义下拉刷新通过自定义List组件RefreshComponent实现。在List容器中添加自定义刷新头部组件和其它的需要刷新部件,RefreshComponent提供了头部样式设置,刷新部件样式设置和刷新回调方法设置。

// FileManagerIndex.ets
RefreshComponent({
  headerStyle: RefreshHeaderStyle.CLOUD, // 头部样式设置
  itemLayout: (): void => this.ContentBody(), // 刷新部件样式
  displayHeight: (
    px2vp(this.deviceDisplay.height) - DimensionUtil.getVp($r('app.float.file_index_title_height'))),
  onRefresh: () => { // 刷新回调方法
    ...
  }
})
  • 头部样式设置。本Codelab提供了DEFAULT默认刷新样式和CLOUD云朵动画刷新样式设置,在RefreshComponent组件初始化时,判断当前刷新样式进行渲染。
// RefreshComponent.ets
if (this.headerStyle === RefreshHeaderStyle.DEFAULT) {
  RefreshDefaultHeader().height(RefreshConstants.REFRESH_HEADER_HEIGHT)
} else if (this.headerStyle === RefreshHeaderStyle.CLOUD) {
  RefreshAnimHeader().height(RefreshConstants.REFRESH_HEADER_HEIGHT)
}
  • 刷新部件样式。刷新部件样式itemLayout为嵌入RefreshComponent组件中的元素,通过@BuilderParam装饰符定义,可根据具体业务需求,当前为默认的Image组件样式。
// FileManagerIndex.ets
@Builder
ContentBody() {
  Image($r('app.media.bg_content'))
    .width(CommonConstants.FULL_LENGTH)
    .height(DimensionUtil.getVp($r('app.float.content_height')))
    .objectFit(ImageFit.Fill)
}
  • 刷新回调方法设置。在手指拖拽刷新头部滑出的过程中计算滑出的距离是否超出可刷新距离,松开手指时如果超出可刷新距离则调用“onRefresh”方法。
// RefreshComponent.ets
// 设置RefreshComponent刷新组件state状态的更新。
@Consume(RefreshConstants.REFRESH_STATE_TAG) @Watch('onStateChanged') state: number;

private onStateChanged() {
  switch (this.state) {
    case RefreshState.REFRESHING:
      if (this.onRefresh !== undefined) {
        this.onRefresh();
      }
      break;
    ...
  }
}

// 监听RefreshComponent中List组件的触摸事件。
List({ scroller: this.listController }) {
  ListItem() {
    Column() {
      ...
    }
    ...
  }
}
...
.onTouch((event?: TouchEvent) => {
  if (!event) {
    return;
  }
  switch (event.type) {
    case TouchType.Down:
      if (this.state === RefreshState.IDLE) {
        this.state = RefreshState.DRAGGING;
      }
      break;
    case TouchType.Move:
      if (this.state === RefreshState.DRAGGING
      && this.listController.currentOffset().yOffset <= -RefreshConstants.REFRESH_EFFECTIVE_HEIGHT) {
        this.state = RefreshState.DRAGGING_REFRESHABLE;
      }
      break;
    case TouchType.Up:
      if (this.state === RefreshState.DRAGGING_REFRESHABLE) {
        this.headerOffset = 0;
        this.state = RefreshState.REFRESHING;
      }
      break;
    default:
      break;
}

// FileManagerIndex.ets
//onRefresh事件没有做相关刷新,只做了模拟延时操作,开发者可以自行加入真实网络加载动作。
onRefresh: () => {
  setTimeout(() => {
    this.state = RefreshState.COMPLETE;
  }, CommonConstants.REFRESH_DEFAULT_TIMEOUT);
}

自定义刷新动画

本Codelab中自定义刷新是由5个图片的组合动画效果。

  • 每个Image通过iconItem参数分别设置各自的x轴偏移量和延时播放的属性动画效果。
// RefreshAnimHeader.ets
@Builder AttrAnimIcons(iconItem: ClassifyModel) {
  Image(iconItem.imgRes)
    .width(px2vp(DimensionUtil.adaptDimension(this.iconWidth)))
    .position({ x: iconItem.posX })
    .objectFit(ImageFit.Contain)
    .animation({
      duration: CommonConstants.REFRESH_HEADER_ITEM_ANIM_DURATION,
      tempo: CommonConstants.REFRESH_HEADER_ITEM_ANIM_TEMPO,
      delay: iconItem.delay,
      curve: Curve.Linear,
      playMode: PlayMode.Alternate,
      iterations: CommonConstants.REFRESH_HEADER_ITEM_ANIM_ITERATIONS
    })
}
  • 监听RefreshComponent刷新组件state状态的变化,当前状态为REFRESHING状态时,改变@State修饰的图片宽度变量iconWidth来启动动画。
// RefreshAnimHeader.ets
@Consume(RefreshConstants.REFRESH_STATE_TAG) @Watch('onStateCheck') state: number;

private onStateCheck() {
  if (this.state === RefreshState.REFRESHING) {
    this.iconWidth = CommonConstants.REFRESH_HEADER_ITEM_SCALE_WIDTH;
  } else {
    this.iconWidth = CommonConstants.REFRESH_HEADER_ITEM_DEFAULT_WIDTH;
  }
}

总结

您已经完成了本次Codelab的学习,并了解到以下知识点:

  1. 使用属性动画实现自定义下拉组件。
  2. 使用属性动画实现自定义刷新组件。
  • 27
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一起学鸿蒙呀~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值