1# Custom Event Dispatch 2 3When handling a touch event, ArkUI performs a touch test on the touch point and the component area before the event is triggered – to determine the components targeted by the event – and dispatches the event based on the test result. You can use **onChildTouchTest** on a parent node to specify how to perform the touch test on child nodes and thereby exert an impact on touch event dispatch. For details about the impact, see [TouchTestStrategy](#touchteststrategy). 4 5> **NOTE** 6> 7> - This feature is supported since API version 11. Updates will be marked with a superscript to indicate their earliest API version. 8> 9> - With use of **onChildTouchTest**, the **onClick**, rotation, and pinch gesture events may receive no response due to the touch target not being hit. 10 11## onChildTouchTest 12 13onChildTouchTest(event: (value: Array<TouchTestInfo>) => TouchResult): T 14 15Called to specify how to perform the touch test on the children of this component. 16 17**Atomic service API**: This API can be used in atomic services since API version 12. 18 19**System capability**: SystemCapability.ArkUI.ArkUI.Full 20 21**Parameters** 22 23| Name| Type | Mandatory| Description | 24| ------ | ------------------------------------------ | ---- | ---------------------- | 25| value | Array<[TouchTestInfo>](#touchtestinfo) | Yes | Array of child components.| 26 27**Return value** 28 29| Type| Description| 30| -------- | -------- | 31| T | Current component.| 32 33>**NOTE** 34> 35>The array of child components contains only components for which **id** is set. 36 37## TouchTestInfo 38 39Provides information about the coordinate system, ID, and size of the component where the current touch point is located. 40 41**Atomic service API**: This API can be used in atomic services since API version 12. 42 43**System capability**: SystemCapability.ArkUI.ArkUI.Full 44 45| Name | Type | Description | 46| ------------- | ------ | ---------------------------------------- | 47| windowX | number | X coordinate of the touch point relative to the upper left corner of the window.<br>Unit: vp.| 48| windowY | number |Y coordinate of the touch point relative to the upper left corner of the window.<br>Unit: vp.| 49| parentX | number |X coordinate of the touch point relative to the upper left corner of the parent component.<br>Unit: vp. | 50| parentY | number |Y coordinate of the touch point relative to the upper left corner of the parent component.<br>Unit: vp. | 51| x | number | X coordinate of the touch point relative to the upper left corner of the child component.<br>Unit: vp.| 52| y | number | Y coordinate of the touch point relative to the upper left corner of the child component.<br>Unit: vp.| 53| rect | [RectResult](ts-types.md#rectresult10) |Size of the child component. | 54| [id](ts-universal-attributes-component-id.md) | string | Component ID.| 55 56## TouchResult 57 58Defines the custom event dispatch result. You can influence event dispatch by returning specific results. 59 60**Atomic service API**: This API can be used in atomic services since API version 12. 61 62**System capability**: SystemCapability.ArkUI.ArkUI.Full 63 64| Name | Type | Mandatory | Description | 65| --------- | --------- | ---- |--------------------------------------- | 66| strategy | [TouchTestStrategy](#touchteststrategy) | Yes | Event dispatch strategy. | 67| id | string | No | Component ID.<br>If **strategy** is set to **TouchTestStrategy.DEFAULT**, **id** is optional. If **strategy** is set to **TouchTestStrategy.FORWARD_COMPETITION** or **TouchTestStrategy.FORWARD**, **id** is mandatory. If **id** is not returned, the strategy **TouchTestStrategy.DEFAULT** is used.| 68 69## TouchTestStrategy 70 71Enumerates the event dispatch strategies. 72 73**Atomic service API**: This API can be used in atomic services since API version 12. 74 75**System capability**: SystemCapability.ArkUI.ArkUI.Full 76 77| Name | Description | 78| ------------| ----------------------------------------- | 79| DEFAULT | Custom dispatch has no effect; the system distributes events based on the hit status of the current node.| 80| FORWARD_COMPETITION | The specified event is forwarded to a particular child node, and the system determines whether to distribute the event to other sibling nodes.| 81| FORWARD | The specified event is forwarded to a particular child node, and the system no longer distributes the event to other sibling nodes.| 82 83## Example 84 85### Example 1: Setting the Event Dispatch Strategy to FORWARD_COMPETITION 86 87In this example, dragging the blank area below the list allows the list to scroll, and clicking the button will trigger its **onClick** event. 88 89```ts 90// xxx.ets 91import { promptAction } from '@kit.ArkUI'; 92 93@Entry 94@Component 95struct ListExample { 96 private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 97 @State text: string = 'Button' 98 99 build() { 100 Column() { 101 List({ space: 12, initialIndex: 0 }) { 102 ForEach(this.arr, (item: number) => { 103 ListItem() { 104 Text('Item ' + item) 105 .width('100%') 106 .height(56) 107 .fontSize(16) 108 .textAlign(TextAlign.Start) 109 }.borderRadius(24) 110 .backgroundColor(Color.White) 111 .padding({ left: 12, right: 12 }) 112 }, (item: string) => item) 113 } 114 .listDirection(Axis.Vertical) 115 .scrollBar(BarState.Off) 116 .edgeEffect(EdgeEffect.Spring) 117 .onScrollIndex((start: number, end: number) => { 118 console.info('first' + start) 119 console.info('last' + end) 120 }) 121 .onDidScroll((scrollOffset: number, scrollState: ScrollState) => { 122 console.info(`onScroll scrollState = ScrollState` + scrollState + `, scrollOffset = ` + scrollOffset) 123 }) 124 .width('100%') 125 .height('65%') 126 .id('MyList') 127 128 Button(this.text) 129 .width(312) 130 .height(40) 131 .id('Mybutton') 132 .fontSize(16) 133 .fontWeight(FontWeight.Medium) 134 .margin({ top: 80 }) 135 .onClick(() => { 136 this.text = 'click the button' 137 promptAction.showToast({ message: 'you click the button.', duration: 3000 }) 138 }) 139 } 140 .width('100%') 141 .height('100%') 142 .backgroundColor(0xF1F3F5) 143 .justifyContent(FlexAlign.End) 144 .padding({ left: 12, right: 12, bottom: 24 }) 145 .onChildTouchTest((touchinfo) => { 146 for (let info of touchinfo) { 147 if (info.id == 'MyList') { 148 return { id: info.id, strategy: TouchTestStrategy.FORWARD_COMPETITION } 149 } 150 } 151 return { strategy: TouchTestStrategy.DEFAULT } 152 }) 153 } 154} 155``` 156 157 158 159### Example 2: Setting the Event Dispatch Strategy to FORWARD 160 161In this example, dragging the blank area below the list allows the list to scroll, but clicking the button will not trigger its **onClick** event. 162 163```ts 164// xxx.ets 165import { promptAction } from '@kit.ArkUI'; 166 167@Entry 168@Component 169struct ListExample { 170 private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 171 @State text: string = 'Button' 172 173 build() { 174 Column() { 175 List({ space: 12, initialIndex: 0 }) { 176 ForEach(this.arr, (item: number) => { 177 ListItem() { 178 Text('Item ' + item) 179 .width('100%') 180 .height(56) 181 .fontSize(16) 182 .textAlign(TextAlign.Start) 183 }.borderRadius(24) 184 .backgroundColor(Color.White) 185 .padding({ left: 12, right: 12 }) 186 }, (item: string) => item) 187 } 188 .listDirection(Axis.Vertical) 189 .scrollBar(BarState.Off) 190 .edgeEffect(EdgeEffect.Spring) 191 .onScrollIndex((start: number, end: number) => { 192 console.info('first' + start) 193 console.info('last' + end) 194 }) 195 .onDidScroll((scrollOffset: number, scrollState: ScrollState) => { 196 console.info(`onScroll scrollState = ScrollState` + scrollState + `, scrollOffset = ` + scrollOffset) 197 }) 198 .width('100%') 199 .height('65%') 200 .id('MyList') 201 202 Button(this.text) 203 .width(312) 204 .height(40) 205 .id('Mybutton') 206 .fontSize(16) 207 .fontWeight(FontWeight.Medium) 208 .margin({ top: 80 }) 209 .onClick(() => { 210 this.text = 'click the button' 211 promptAction.showToast({ message: 'you click the button.', duration: 3000 }) 212 }) 213 } 214 .width('100%') 215 .height('100%') 216 .backgroundColor(0xF1F3F5) 217 .justifyContent(FlexAlign.End) 218 .padding({ left: 12, right: 12, bottom: 24 }) 219 .onChildTouchTest((touchinfo) => { 220 for (let info of touchinfo) { 221 if (info.id == 'MyList') { 222 return { id: info.id, strategy: TouchTestStrategy.FORWARD } 223 } 224 } 225 return { strategy: TouchTestStrategy.DEFAULT } 226 }) 227 } 228} 229``` 230 231 232 233### Example 3: Setting the Event Dispatch Strategy to DEFAULT 234 235In this example, dragging the blank area below the list will not scroll the list, and clicking the button will trigger its **onClick** event. 236 237```ts 238// xxx.ets 239import { promptAction } from '@kit.ArkUI'; 240 241@Entry 242@Component 243struct ListExample { 244 private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 245 @State text: string = 'Button' 246 247 build() { 248 Column() { 249 List({ space: 12, initialIndex: 0 }) { 250 ForEach(this.arr, (item: number) => { 251 ListItem() { 252 Text('Item ' + item) 253 .width('100%') 254 .height(56) 255 .fontSize(16) 256 .textAlign(TextAlign.Start) 257 }.borderRadius(24) 258 .backgroundColor(Color.White) 259 .padding({ left: 12, right: 12 }) 260 }, (item: string) => item) 261 } 262 .listDirection(Axis.Vertical) 263 .scrollBar(BarState.Off) 264 .edgeEffect(EdgeEffect.Spring) 265 .onScrollIndex((start: number, end: number) => { 266 console.info('first' + start) 267 console.info('last' + end) 268 }) 269 .onDidScroll((scrollOffset: number, scrollState: ScrollState) => { 270 console.info(`onScroll scrollState = ScrollState` + scrollState + `, scrollOffset = ` + scrollOffset) 271 }) 272 .width('100%') 273 .height('65%') 274 .id('MyList') 275 276 Button(this.text) 277 .width(312) 278 .height(40) 279 .id('Mybutton') 280 .fontSize(16) 281 .fontWeight(FontWeight.Medium) 282 .margin({ top: 80 }) 283 .onClick(() => { 284 this.text = 'click the button' 285 promptAction.showToast({ message: 'you click the button.', duration: 3000 }) 286 }) 287 } 288 .width('100%') 289 .height('100%') 290 .backgroundColor(0xF1F3F5) 291 .justifyContent(FlexAlign.End) 292 .padding({ left: 12, right: 12, bottom: 24 }) 293 .onChildTouchTest((touchinfo) => { 294 return { strategy: TouchTestStrategy.DEFAULT } 295 }) 296 } 297} 298``` 299 300 301