1# 标题下拉缩放案例 2 3### 介绍 4 5本文以备忘录应用为示例,介绍如何在实现标题跟随手势移动并放缩的动效。 6 7### 效果图预览 8 9 10 11**使用说明**: 12 131. 进入页面,起初标题并没有展开,与增加/分享的菜单在同一行。 142. 进行第一次下拉操作,此时标题跟随手势慢慢放大,并渐渐显示笔记数目信息。 153. 继续下拉,标题与菜单都下拉一段距离,并放大,达到阈值距离后标题大小不再发生变化;松手后回弹至第一次下拉后的状态。 164. 向上滑动,标题随手势折叠,回到初始时的状态。 17 18### 实现思路 19 201. 标题高度变化,通过状态变量heightValue控制,通过onScrollFrameBegin获取list偏移,并将其分配给标题高度变化和实际list偏移。源码参考[TitleExpansion.ets](./entry/src/main/ets/utils/TitleExpansion.ets)。 21 22 ```ts 23 List({ space: Constants.SEARCH_MEMO_SPACE, scroller: this.scroller }) { 24 ListItem() { 25 // 内容 26 this.content(); 27 } 28 } 29 .onScrollFrameBegin((offset: number, state: ScrollState) => { 30 let listOffset: number = 0; 31 console.log(`offset: ${offset}`) 32 // 保证list没有在顶部时以list滑动为主 33 if (offset < 0) { 34 listOffset = Math.max(offset, -this.scroller.currentOffset().yOffset); 35 offset -= listOffset; 36 } 37 // 标题高度变化 38 let titleHeightChange = this.getTitleHeightChangeOptions(-offset); 39 this.heightValue += titleHeightChange; 40 // list滑动距离 41 offset += titleHeightChange; 42 offset += listOffset; 43 return {offsetRemain: offset}; 44 }) 45 ``` 46 472. 标题展开继续下拉偏移,通过状态变量curOffset控制,通过onDidScroll获取标题展开后,标题继续下拉的偏移。 源码参考[TitleExpansion.ets](./entry/src/main/ets/utils/TitleExpansion.ets)。 48 49 ```ts 50 List({ space: Constants.SEARCH_MEMO_SPACE, scroller: this.scroller }) { 51 ListItem() { 52 // 内容 53 this.content(); 54 } 55 } 56 // 获取标题展开后,标题继续下拉偏移 57 .onDidScroll((scrollOffset: number, scrollState: ScrollState) => { 58 this.curOffset = this.scroller.currentOffset().yOffset; 59 }) 60 ``` 61 623. 滚动停止动画,通过onScrollStop获取滚动停止时的标题高度。当标题高度大于阈值时,产生展开标题动画;相反,则产生收缩标题动画。源码参考[TitleExpansion.est](./entry/src/main/ets/utils/TitleExpansion.ets) 63 64```typescript 65List({ space: Constants.SEARCH_MEMO_SPACE, scroller: this.scroller }) { 66 ListItem() { 67 // 内容 68 this.content(); 69 } 70} 71// TODO: 知识点: 在滚动停止时判断是否需要展开或者收缩标题 72.onScrollStop(() => { 73 if (this.heightValue >= this.thresholdValue) { 74 this.animateToThrottle(() => { 75 this.heightValue = Constants.EXPAND_TITLE_HEIGHT; 76 }, this.delay) 77 } else { 78 this.animateToThrottle(() => { 79 this.heightValue = Constants.NORMAL_TITLE_HEIGHT; 80 }, this.delay) 81 } 82}) 83``` 84 854. 响应状态变量,标题和菜单的tranlate和scale参数以及笔记数量的opacity参数在下拉过程中会更新。源码参考[TitleExpansion.ets](./entry/src/main/ets/utils/TitleExpansion.ets)。 86 87 ```ts 88 /** 89 * 获取标题展开时,继续下拉的菜单栏Translate参数 90 * @returns {TranslateOptions} 标题展开后继续下拉的菜单栏Translate参数 91 */ 92 getMenuTranslateOptions(): TranslateOptions { 93 return { y: Math.max(-this.curOffset, 0) }; 94 } 95 96 /** 97 * 获取标题展开时,继续下拉的标题栏Translate参数 98 * @returns {TranslateOptions} 标题展开后继续下拉的标题栏Translate参数 99 */ 100 getTitleTranslateOptions(): TranslateOptions { 101 return {y: Math.max(-this.curOffset, 0)}; 102 } 103 104 /** 105 * 获取标题栏高度变化参数 106 * @param offset: 当前产生的偏移 107 * @returns {number} 标题栏高度变化值 108 */ 109 getTitleHeightChangeOptions(offset: number): number { 110 return Math.max(Math.min(offset, this.animationAttribute.expandTitleHeight - this.heightValue), this.animationAttribute.normalTitleHeight - this.heightValue); 111 } 112 113 /** 114 * 获取主标题缩放的Scale参数 115 * @returns {ScaleOptions} 主标题缩放系数 116 */ 117 getTitleScaleOptions(): ScaleOptions { 118 let scaleRatio = 1 + (this.animationAttribute.titleScale - 1) * 119 Math.min((this.heightValue - this.animationAttribute.normalTitleHeight + Math.max(-this.curOffset, 0)) / this.animationAttribute.continuePullThreshold, 1); 120 return { 121 x: scaleRatio, 122 y: scaleRatio, 123 centerX: Constants.INIT_COORDINATE, 124 centerY: Constants.INIT_COORDINATE 125 }; 126 } 127 128 /** 129 * 获取子标题显隐参数 130 * @returns {number} 子标题显隐系数 131 */ 132 getTitleOpacityOptions(): number { 133 return (this.heightValue - this.animationAttribute.normalTitleHeight) / 134 (this.animationAttribute.expandTitleHeight - this.animationAttribute.normalTitleHeight) 135 } 136 ``` 137 138### 高性能知识点 139 140本示例使用了[LazyForEach](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/quick-start/arkts-rendering-control-lazyforeach.md)进行数据懒加载以及[显式动画animateTo](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-explicit-animation.md)实现文本偏移。 141 142### 工程结构&模块类型 143 144``` 145expandtitle // har类型 146|---constants 147| |---Constants.ets // 常量池 148|---model 149| |---AnimationAttribute.ets // 动效属性 150| |---TitleAttribute.ets // 标题属性 151|---pages 152| |---Configure.ets // 样例配置文件 153| |---DataSource.ets // 懒加载数据源 154| |---MemoInfo.ets // 数据类型 155| |---MemoItem.ets // 笔记视图 156| |---MockData.ets // 模拟数据 157| |---TitleContent.ets // 内容界面 158| |---Index.ets // 标题扩展组件UI样例 159| |---TitleMenu.ets // 菜单栏 160|---utils 161| |---TitleExpansion.ets // 标题扩展组件 162``` 163 164### 参考资料 165 166[显式动画animateTo](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-explicit-animation.md) 167 168[数据懒加载LazyForEach](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/quick-start/arkts-rendering-control-lazyforeach.md) 169 170### 约束与限制 171 1721.本示例仅支持在标准系统上运行。 173 1742.本示例需要使用DevEco Studio 5.0.0 Release 才可编译运行。 175 176### 下载 177 178如需单独下载本工程,执行如下命令: 179```javascript 180git init 181git config core.sparsecheckout true 182echo /code/UI/ExpandTitle/ > .git/info/sparse-checkout 183git remote add origin https://gitee.com/openharmony/applications_app_samples.git 184git pull origin master 185```