首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

HarmonyOS鸿蒙开发实战( Beta5.0)标题下拉缩放实践案例

  • 25-03-03 06:42
  • 4359
  • 13998
blog.csdn.net

鸿蒙HarmonyOS NEXT开发实战往期文章必看(持续更新......)

HarmonyOS NEXT应用开发性能实践总结

HarmonyOS NEXT应用开发案例实践总结合集

最新版!“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!(从零基础入门到精通)

非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!


介绍

本文以备忘录应用为示例,介绍如何在实现标题展开时继续下拉的动效。

效果图预览

使用说明:

  1. 进入页面,起初标题并没有展开,与增加/分享的菜单在同一行。
  2. 进行第一次下拉操作,此时标题展开至目标位置,并显示笔记数目信息,与菜单不在同一行。
  3. 继续下拉,达到阈值距离后,标题与菜单都下拉一段距离,并放大;松手后回弹至第一次下拉后的状态。
  4. 向上滑动,标题折叠,回到初始时的状态。

实现思路

  1. 标题是否展开,通过状态变量isExpanded控制,展开后原先标题置空,将展开后标题设置为可见。源码参考TitleExpansion.ets。

    1. Column() {
    2. Row() {
    3. Text(!this.isExpanded ? $r('app.string.expanded_title_memo_title') : '') // 展开前的标题
    4. .fontSize($r('app.string.expanded_title_init_title_font_size'))
    5. ......
    6. }
    7. .width($r('app.string.expanded_title_layout_100_percent'))
    8. .padding($r('app.string.expanded_title_layout_25'))
    9. .margin({ top: $r('app.string.expanded_title_layout_10') })
    10. .alignItems(VerticalAlign.Center)
    11. .translate(this.getMenuTranslateOptions())
    12. .animation({ duration: this.duration, curve: Curve.FastOutLinearIn })
    13. if (this.isExpanded) { // 展开后的标题
    14. Column() {
    15. Text($r('app.string.expanded_title_memo_title'))
    16. .fontSize($r('app.string.expanded_title_font_size'))
    17. Text($r('app.string.expanded_title_memo_counts'))
    18. .fontSize($r('app.string.expanded_title_memo_counts_font_size'))
    19. .fontColor(Color.Grey)
    20. }
    21. .width($r('app.string.expanded_title_layout_100_percent'))
    22. .padding({ left: $r('app.string.expanded_title_layout_25') })
    23. .margin({ top: $r('app.string.expanded_title_layout_10') })
    24. .alignItems(HorizontalAlign.Start)
    25. .translate(this.getTitleTranslateOptions())
    26. .scale(this.getTitleScaleOptions())
    27. .animation({ duration: this.duration, curve: Curve.FastOutLinearIn })
    28. .transition({ type: TransitionType.Insert, translate: { y: Constants.TRANSLATE_Y } })
    29. }
    30. }
  2. 内容高度变化,通过状态变量heightValue控制,标题展开时设置为较小值,以提供标题展开后的空间。源码参考TitleExpansion.ets。

    1. Column() {
    2. List({ space: Constants.SEARCH_MEMO_SPACE }) {
    3. ListItem() {
    4. Search({ placeholder: $r('app.string.expanded_title_search_placeholder') })
    5. .width($r('app.string.expanded_title_layout_100_percent'))
    6. .height($r('app.string.expanded_title_layout_8_percent'))
    7. .backgroundColor(Color.White)
    8. }
    9. LazyForEach(this.memoData, (item: MemoInfo) => {
    10. ListItem() {
    11. MemoItem({ memoItem: item })
    12. }
    13. }, (item: MemoInfo) => JSON.stringify(item))
    14. }
    15. .scrollBar(BarState.Off)
    16. .margin({ left: $r('app.string.expanded_title_layout_10'), right: $r('app.string.expanded_title_layout_10') })
    17. .width($r('app.string.expanded_title_layout_90_percent'))
    18. .height($r('app.string.expanded_title_layout_100_percent'))
    19. .onReachStart(() => { // TODO:知识点:通过onReachStart回调,更新列表是否位于顶部的状态更新,以控制仅在顶部时才触发标题下移放大动效
    20. this.atStart = true;
    21. })
    22. }
    23. .width($r('app.string.expanded_title_layout_100_percent'))
    24. .height(this.heightValue) // 通过状态变量heightValue控制内容高度变化
    25. .animation({ duration: this.duration, curve: Curve.FastOutLinearIn })
    26. .onTouch((event: TouchEvent) => this.handleTouchEvent(event))
  3. 状态变量更新都在onTouch时间的响应函数handleTouchEvent中处理,根据手指滑动类型TouchType分为三种情况处理:

    • TouchType.Down,即手指下按时:记录按下时的坐标downY,并更新状态变量isMoving为开始滑动、duration为初始动画时长
    • TouchType.Move,即手指滑动时:根据滑动方向的不同,更新滑动距离offsetY、内容高度heightValue、标题是否展开等状态变量
    • TouchType.Up、TouchType.Cancel,即滑动结束时:更新状态变量isMoving为停止滑动、duration为回弹动画时长

    源码参考TitleExpansion.ets。

    1. handleTouchEvent(event: TouchEvent): void {
    2. switch (event.type) {
    3. // 手指下按时
    4. case TouchType.Down:
    5. this.downY = event.touches[0].y;
    6. this.lastMoveY = event.touches[0].y;
    7. this.isMoving = true;
    8. this.duration = Constants.ANIMATE_DURATION_DRAG; // 重置动画持续时间
    9. break;
    10. // 手指滑动时
    11. case TouchType.Move:
    12. const delta = event.touches[0].y - this.lastMoveY;
    13. this.offsetY = event.touches[0].y - this.downY;
    14. if (delta < 0) { // TODO:知识点:手势为上滑时
    15. this.heightValue = $r('app.string.expanded_title_memo_area_height_before');
    16. this.isExpanded = false;
    17. this.atStart = false;
    18. }
    19. if (delta > 0 && this.atStart) { // TODO:知识点:手势为下滑,且列表内容位于顶部时
    20. // 性能知识点:手指滑动的时,直接使用animateTo,会创建大量的animateTo对象,可以通过节流器优化性能
    21. this.animateToThrottle(() => {
    22. this.heightValue = $r('app.string.expanded_title_memo_area_height_after');
    23. this.isExpanded = true;
    24. }, 1000);
    25. }
    26. this.lastMoveY = event.touches[0].y;
    27. break;
    28. // 滑动结束时
    29. case TouchType.Up:
    30. case TouchType.Cancel:
    31. this.isMoving = false;
    32. this.duration = Constants.ANIMATE_DURATION_BACK; // 控制回弹动画时间
    33. break;
    34. }
    35. }
  4. 响应状态变量的动画,通过为标题和菜单绑定属性动画animation实现,标题和菜单的tranlate和scale参数在下拉过程中会更新, 并通过isContinuePullDown判断触发与否。源码参考TitleExpansion.ets。

    1. /**
    2. * 获取标题展开时,图标继续下拉的Translate参数
    3. */
    4. getMenuTranslateOptions(): TranslateOptions {
    5. return this.isContinuePullDown() ? {
    6. y: Math.min(this.offsetY - Constants.CONTENT_DOWN_Y_THRESHOLD, Constants.MENU_DOWN_Y_MAX_VALUE)
    7. } : { y: Constants.INIT_COORDINATE };
    8. }
    9. /**
    10. * 获取标题展开时,标题继续下拉的Translate参数
    11. */
    12. getTitleTranslateOptions(): TranslateOptions {
    13. return this.isContinuePullDown() ? {
    14. y: Math.min(this.offsetY - Constants.CONTENT_DOWN_Y_THRESHOLD, Constants.TITLE_DOWN_Y_MAX_VALUE)
    15. } : { y: Constants.INIT_COORDINATE };
    16. }
    17. /**
    18. * 获取标题展开时,标题缩放的Scale参数
    19. */
    20. getTitleScaleOptions(): ScaleOptions {
    21. return this.isContinuePullDown() ? {
    22. x: Constants.TITLE_SCALE_MAX_VALUE,
    23. y: Constants.TITLE_SCALE_MAX_VALUE,
    24. centerX: Constants.INIT_COORDINATE,
    25. centerY: Constants.INIT_COORDINATE
    26. } : {
    27. x: Constants.TITLE_SCALE_DEFAULT_VALUE,
    28. y: Constants.TITLE_SCALE_DEFAULT_VALUE,
    29. centerX: Constants.INIT_COORDINATE,
    30. centerY: Constants.INIT_COORDINATE
    31. };
    32. }
    33. /**
    34. * 判断是否达到触发继续下拉动效的条件
    35. */
    36. isContinuePullDown(): boolean {
    37. return this.isMoving && this.isExpanded && this.offsetY >= Constants.CONTENT_DOWN_Y_THRESHOLD;
    38. }

高性能知识点

本示例使用了LazyForEach进行数据懒加载以及显式动画animateTo实现文本偏移。

工程结构&模块类型

  1. marquee // har类型
  2. |---model
  3. | |---Constants.ets // 数据模型层-常量
  4. | |---DataSource.ets // 数据模型层-懒加载数据源
  5. | |---MemoInfo.ets // 数据模型层-数据类型
  6. | |---MockData.ets // 数据模型层-模拟数据
  7. |---view
  8. | |---MemoItem.ets // 视图层-笔记视图
  9. |---page
  10. | |---TitleExpansion.ets // 页面层-方案主页面

鸿蒙NEXT全套学习资料
微信名片
注:本文转载自blog.csdn.net的让开,我要吃人了的文章"https://blog.csdn.net/weixin_55362248/article/details/142555426"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top