1# 组件可见区域变化事件 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @jiangtao92--> 5<!--Designer: @piggyguy--> 6<!--Tester: @songyanhong--> 7<!--Adviser: @HelloCrease--> 8 9组件可见区域变化事件是组件在屏幕中的显示区域面积变化时触发的事件,提供了判断组件是否完全或部分显示在屏幕中的能力,适用于广告曝光埋点之类的场景。 10 11> **说明:** 12> 13> 从API version 9开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 14 15## onVisibleAreaChange 16 17onVisibleAreaChange(ratios: Array<number>, event: VisibleAreaChangeCallback): T 18 19组件可见区域变化时触发该回调。 20 21**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 22 23**系统能力:** SystemCapability.ArkUI.ArkUI.Full 24 25**参数:** 26 27| 参数名 | 类型 | 必填 | 说明 | 28| ------ | --------------------------------------------------- | ---- | ------------------------------------------------------------ | 29| ratios | Array<number> | 是 | 阈值数组。其中,每个阈值代表组件可见面积(即组件在屏幕显示区的面积,只计算父组件内的面积,超出父组件部分不会计算)与组件自身面积的比值。当组件可见面积与自身面积的比值接近阈值时,均会触发该回调。每个阈值的取值范围为[0.0, 1.0],如果开发者设置的阈值超出该范围,则会实际取值0.0或1.0。<br/>**说明:** <br/>当数值接近边界0和1时,将会按照误差不超过0.001的规则进行舍入。例如,0.9997会被近似为1。 | 30| event | [VisibleAreaChangeCallback](./ts-universal-component-visible-area-change-event.md#visibleareachangecallback12) | 是 | 组件可见区域变化事件的回调。 | 31 32**返回值:** 33 34| 类型 | 说明 | 35| -------- | -------- | 36| T | 返回当前组件。 | 37 38> **说明:** 39> 40> 41>- 仅提供自身节点相对于所有祖先节点(直到window边界)的相对裁切面积与自身面积的比值及其变化趋势。 42> 43>- 不支持兄弟组件对自身节点的遮挡计算,不支持所有祖先的兄弟节点对自身节点的遮挡计算,如[Stack](ts-container-stack.md)、[Z序控制](ts-universal-attributes-z-order.md)等。 44> 45>- 不支持非挂树节点的可见面积变化计算。例如,预加载的节点、通过[overlay](ts-universal-attributes-overlay.md#overlay)能力挂载的自定义节点。 46 47## onVisibleAreaApproximateChange<sup>17+</sup> 48 49onVisibleAreaApproximateChange(options: VisibleAreaEventOptions, event: VisibleAreaChangeCallback | undefined): void 50 51设置[onVisibleAreaChange](./ts-universal-component-visible-area-change-event.md#onvisibleareachange)事件的回调参数,限制它的执行间隔。 52 53**原子化服务API:** 从API version 17开始,该接口支持在原子化服务中使用。 54 55**系统能力:** SystemCapability.ArkUI.ArkUI.Full 56 57**参数:** 58 59| 参数名 | 类型 | 必填 | 说明 | 60| ------ | ------ | ---- | -------------------------- | 61| options | [VisibleAreaEventOptions](#visibleareaeventoptions12) | 是 | 可见区域变化相关的参数。 | 62| event | [VisibleAreaChangeCallback](#visibleareachangecallback12) \| undefined | 是 | onVisibleAreaChange事件的回调函数。当组件可见面积与自身面积的比值接近options中设置的阈值时触发该回调。 | 63 64>**说明:** 65> 66> 此接口与[onVisibleAreaChange](./ts-universal-component-visible-area-change-event.md#onvisibleareachange)接口存在如下差异,onVisibleAreaChange在每一帧都会进行可见区域比例的计算,如果注册节点太多,系统功耗存在劣化。此接口降低了可见区域比例计算的频度,计算间隔由[VisibleAreaEventOptions](#visibleareaeventoptions12)的expectedUpdateInterval参数决定。 67> 68> 当前接口的可见区域回调阈值默认包含0。例如,开发者设置回调阈值为[0.5],实际生效的阈值为[0.0, 0.5]。 69 70## VisibleAreaEventOptions<sup>12+</sup> 71 72关于区域变化相关的参数。 73 74**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 75 76**系统能力:** SystemCapability.ArkUI.ArkUI.Full 77 78| 参数名 | 类型 | 只读 | 可选 | 说明 | 79| ------ | --------------------------------------------------- | ---- | -------- | ------------------------------------------------------------ | 80| ratios | Array<number> | 否 | 否 | 阈值数组。其中,每个阈值代表组件可见面积(即组件在屏幕显示区的面积,只计算父组件内的面积,超出父组件部分不会计算)与组件自身面积的比值。每个阈值的取值范围为[0.0, 1.0],如果开发者设置的阈值超出该范围,则会实际取值0.0或1.0。 | 81| expectedUpdateInterval | number | 否 | 是 | 定义了开发者期望的计算间隔,单位为ms。默认值:1000| 82 83## VisibleAreaChangeCallback<sup>12+</sup> 84 85组件可见区域变化事件的回调类型。 86 87type VisibleAreaChangeCallback = (isExpanding: boolean, currentRatio: number) => void 88 89**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 90 91**系统能力:** SystemCapability.ArkUI.ArkUI.Full 92 93**参数:** 94 95| 参数名 | 类型 | 必填 | 说明 | 96| ------------- | ------------------ | ------------- | ---------------------- | 97| isExpanding | boolean | 是 | 视组件的可见面积与自身面积的比值与上一次回调相比的情况而定,比值变大为true,比值变小为false。 | 98| currentRatio | number | 是 | 触发回调时,组件可见面积与自身面积的比值。 | 99 100## 示例 101 102### 示例1 (使用onVisibleAreaChange来监听区域变化) 103 104该示例对组件设置onVisibleAreaChange事件,当组件完全显示或者完全消失时触发回调。 105 106```ts 107// xxx.ets 108@Entry 109@Component 110struct ScrollExample { 111 scroller: Scroller = new Scroller() 112 private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 113 @State testTextStr: string = 'test' 114 @State testRowStr: string = 'test' 115 116 build() { 117 Column() { 118 Column() { 119 Text(this.testTextStr) 120 .fontSize(20) 121 122 Text(this.testRowStr) 123 .fontSize(20) 124 } 125 .height(100) 126 .backgroundColor(Color.Gray) 127 .opacity(0.3) 128 129 Scroll(this.scroller) { 130 Column() { 131 Text("Test Text Visible Change") 132 .fontSize(20) 133 .height(200) 134 .margin({ top: 50, bottom: 20 }) 135 .backgroundColor(Color.Green) 136 // 通过设置ratios为[0.0, 1.0],实现当组件完全显示或完全消失在屏幕中时触发回调。 137 .onVisibleAreaChange([0.0, 1.0], (isExpanding: boolean, currentRatio: number) => { 138 console.info('Test Text isExpanding: ' + isExpanding + ', currentRatio:' + currentRatio) 139 if (isExpanding && currentRatio >= 1.0) { 140 console.info('Test Text is fully visible. currentRatio:' + currentRatio) 141 this.testTextStr = 'Test Text is fully visible' 142 } 143 144 if (!isExpanding && currentRatio <= 0.0) { 145 console.info('Test Text is completely invisible.') 146 this.testTextStr = 'Test Text is completely invisible' 147 } 148 }) 149 150 Row() { 151 Text('Test Row Visible Change') 152 .fontSize(20) 153 .margin({ bottom: 20 }) 154 155 } 156 .height(200) 157 .backgroundColor(Color.Yellow) 158 .onVisibleAreaChange([0.0, 1.0], (isExpanding: boolean, currentRatio: number) => { 159 console.info('Test Row isExpanding:' + isExpanding + ', currentRatio:' + currentRatio) 160 if (isExpanding && currentRatio >= 1.0) { 161 console.info('Test Row is fully visible.') 162 this.testRowStr = 'Test Row is fully visible' 163 } 164 165 if (!isExpanding && currentRatio <= 0.0) { 166 console.info('Test Row is completely invisible.') 167 this.testRowStr = 'Test Row is completely invisible' 168 } 169 }) 170 171 ForEach(this.arr, (item:number) => { 172 Text(item.toString()) 173 .width('90%') 174 .height(150) 175 .backgroundColor(0xFFFFFF) 176 .borderRadius(15) 177 .fontSize(16) 178 .textAlign(TextAlign.Center) 179 .margin({ top: 10 }) 180 }, (item:number) => (item.toString())) 181 182 }.width('100%') 183 } 184 .backgroundColor(0x317aff) 185 .scrollable(ScrollDirection.Vertical) 186 .scrollBar(BarState.On) 187 .scrollBarColor(Color.Gray) 188 .scrollBarWidth(10) 189 .onWillScroll((xOffset: number, yOffset: number, scrollState: ScrollState) => { 190 console.info(xOffset + ' ' + yOffset) 191 }) 192 .onScrollEdge((side: Edge) => { 193 console.info('To the edge') 194 }) 195 .onScrollStop(() => { 196 console.info('Scroll Stop') 197 }) 198 199 }.width('100%').height('100%').backgroundColor(0xDCDCDC) 200 } 201} 202``` 203 204### 示例2 (使用onVisibleAreaApproximateChange来监听区域变化) 205 206该示例对组件设置onVisibleAreaApproximateChange事件,当组件完全显示或者完全消失时触发回调。 207 208```ts 209// xxx.ets 210@Entry 211@Component 212struct ScrollExample { 213 scroller: Scroller = new Scroller() 214 private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 215 @State testTextStr: string = 'test' 216 @State testRowStr: string = 'test' 217 218 build() { 219 Column() { 220 Column() { 221 Text(this.testTextStr) 222 .fontSize(20) 223 224 Text(this.testRowStr) 225 .fontSize(20) 226 } 227 .height(100) 228 .backgroundColor(Color.Gray) 229 .opacity(0.3) 230 231 Scroll(this.scroller) { 232 Column() { 233 Text("Test Text Visible Change") 234 .fontSize(20) 235 .height(200) 236 .margin({ top: 50, bottom: 20 }) 237 .backgroundColor(Color.Green) 238 // 通过设置ratios为[0.0, 1.0],实现当组件完全显示或完全消失在屏幕中时触发回调。 239 .onVisibleAreaApproximateChange({ratios: [0.0, 1.0], expectedUpdateInterval: 1000}, (isExpanding: boolean, currentRatio: number) => { 240 console.info('Test Text isExpanding: ' + isExpanding + ', currentRatio:' + currentRatio) 241 if (isExpanding && currentRatio >= 1.0) { 242 console.info('Test Text is fully visible. currentRatio:' + currentRatio) 243 this.testTextStr = 'Test Text is fully visible' 244 } 245 246 if (!isExpanding && currentRatio <= 0.0) { 247 console.info('Test Text is completely invisible.') 248 this.testTextStr = 'Test Text is completely invisible' 249 } 250 }) 251 252 Row() { 253 Text('Test Row Visible Change') 254 .fontSize(20) 255 .margin({ bottom: 20 }) 256 257 } 258 .height(200) 259 .backgroundColor(Color.Yellow) 260 .onVisibleAreaChange([0.0, 1.0], (isExpanding: boolean, currentRatio: number) => { 261 console.info('Test Row isExpanding:' + isExpanding + ', currentRatio:' + currentRatio) 262 if (isExpanding && currentRatio >= 1.0) { 263 console.info('Test Row is fully visible.') 264 this.testRowStr = 'Test Row is fully visible' 265 } 266 267 if (!isExpanding && currentRatio <= 0.0) { 268 console.info('Test Row is completely invisible.') 269 this.testRowStr = 'Test Row is completely invisible' 270 } 271 }) 272 273 ForEach(this.arr, (item:number) => { 274 Text(item.toString()) 275 .width('90%') 276 .height(150) 277 .backgroundColor(0xFFFFFF) 278 .borderRadius(15) 279 .fontSize(16) 280 .textAlign(TextAlign.Center) 281 .margin({ top: 10 }) 282 }, (item:number) => (item.toString())) 283 284 }.width('100%') 285 } 286 .backgroundColor(0x317aff) 287 .scrollable(ScrollDirection.Vertical) 288 .scrollBar(BarState.On) 289 .scrollBarColor(Color.Gray) 290 .scrollBarWidth(10) 291 .onWillScroll((xOffset: number, yOffset: number, scrollState: ScrollState) => { 292 console.info(xOffset + ' ' + yOffset) 293 }) 294 .onScrollEdge((side: Edge) => { 295 console.info('To the edge') 296 }) 297 .onScrollStop(() => { 298 console.info('Scroll Stop') 299 }) 300 301 }.width('100%').height('100%').backgroundColor(0xDCDCDC) 302 } 303} 304``` 305 306