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.| 48| windowY | number |Y coordinate of the touch point relative to the upper left corner of the window.| 49| parentX | number |X coordinate of the touch point relative to the upper left corner of the parent component. | 50| parentY | number |Y coordinate of the touch point relative to the upper left corner of the parent component. | 51| x | number | X coordinate of the touch point relative to the upper left corner of the child component.| 52| y | number | Y coordinate of the touch point relative to the upper left corner of the child component.| 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**Widget capability**: This API can be used in ArkTS widgets since API version 11. 74 75**Atomic service API**: This API can be used in atomic services since API version 12. 76 77**System capability**: SystemCapability.ArkUI.ArkUI.Full 78 79| Name | Description | 80| ------------| ----------------------------------------- | 81| DEFAULT | Custom dispatch has no effect; the system distributes events based on the hit status of the current node.| 82| 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.| 83| FORWARD | The specified event is forwarded to a particular child node, and the system no longer distributes the event to other sibling nodes.| 84 85## Example 86 87### Example 1: Setting the Event Dispatch Strategy to FORWARD_COMPETITION 88 89In this example, dragging the blank area below the list allows the list to scroll, and clicking the button will trigger its **onClick** event. 90 91```ts 92// xxx.ets 93import { promptAction } from '@kit.ArkUI'; 94 95@Entry 96@Component 97struct ListExample { 98 private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 99 @State text: string = 'Button' 100 101 build() { 102 Column() { 103 List({ space: 12, initialIndex: 0 }) { 104 ForEach(this.arr, (item: number) => { 105 ListItem() { 106 Text('Item ' + item) 107 .width('100%') 108 .height(56) 109 .fontSize(16) 110 .textAlign(TextAlign.Start) 111 }.borderRadius(24) 112 .backgroundColor(Color.White) 113 .padding({ left: 12, right: 12 }) 114 }, (item: string) => item) 115 } 116 .listDirection(Axis.Vertical) 117 .scrollBar(BarState.Off) 118 .edgeEffect(EdgeEffect.Spring) 119 .onScrollIndex((start: number, end: number) => { 120 console.info('first' + start) 121 console.info('last' + end) 122 }) 123 .onDidScroll((scrollOffset: number, scrollState: ScrollState) => { 124 console.info(`onScroll scrollState = ScrollState` + scrollState + `, scrollOffset = ` + scrollOffset) 125 }) 126 .width('100%') 127 .height('65%') 128 .id('MyList') 129 130 Button(this.text) 131 .width(312) 132 .height(40) 133 .id('Mybutton') 134 .fontSize(16) 135 .fontWeight(FontWeight.Medium) 136 .margin({ top: 80 }) 137 .onClick(() => { 138 this.text = 'click the button' 139 promptAction.showToast({ message: 'you click the button.', duration: 3000 }) 140 }) 141 } 142 .width('100%') 143 .height('100%') 144 .backgroundColor(0xF1F3F5) 145 .justifyContent(FlexAlign.End) 146 .padding({ left: 12, right: 12, bottom: 24 }) 147 .onChildTouchTest((touchinfo) => { 148 for (let info of touchinfo) { 149 if (info.id == 'MyList') { 150 return { id: info.id, strategy: TouchTestStrategy.FORWARD_COMPETITION } 151 } 152 } 153 return { strategy: TouchTestStrategy.DEFAULT } 154 }) 155 } 156} 157``` 158 159 160 161### Example 2: Setting the Event Dispatch Strategy to FORWARD 162 163In this example, dragging the blank area below the list allows the list to scroll, but clicking the button will not trigger its **onClick** event. 164 165```ts 166// xxx.ets 167import { promptAction } from '@kit.ArkUI'; 168 169@Entry 170@Component 171struct ListExample { 172 private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 173 @State text: string = 'Button' 174 175 build() { 176 Column() { 177 List({ space: 12, initialIndex: 0 }) { 178 ForEach(this.arr, (item: number) => { 179 ListItem() { 180 Text('Item ' + item) 181 .width('100%') 182 .height(56) 183 .fontSize(16) 184 .textAlign(TextAlign.Start) 185 }.borderRadius(24) 186 .backgroundColor(Color.White) 187 .padding({ left: 12, right: 12 }) 188 }, (item: string) => item) 189 } 190 .listDirection(Axis.Vertical) 191 .scrollBar(BarState.Off) 192 .edgeEffect(EdgeEffect.Spring) 193 .onScrollIndex((start: number, end: number) => { 194 console.info('first' + start) 195 console.info('last' + end) 196 }) 197 .onDidScroll((scrollOffset: number, scrollState: ScrollState) => { 198 console.info(`onScroll scrollState = ScrollState` + scrollState + `, scrollOffset = ` + scrollOffset) 199 }) 200 .width('100%') 201 .height('65%') 202 .id('MyList') 203 204 Button(this.text) 205 .width(312) 206 .height(40) 207 .id('Mybutton') 208 .fontSize(16) 209 .fontWeight(FontWeight.Medium) 210 .margin({ top: 80 }) 211 .onClick(() => { 212 this.text = 'click the button' 213 promptAction.showToast({ message: 'you click the button.', duration: 3000 }) 214 }) 215 } 216 .width('100%') 217 .height('100%') 218 .backgroundColor(0xF1F3F5) 219 .justifyContent(FlexAlign.End) 220 .padding({ left: 12, right: 12, bottom: 24 }) 221 .onChildTouchTest((touchinfo) => { 222 for (let info of touchinfo) { 223 if (info.id == 'MyList') { 224 return { id: info.id, strategy: TouchTestStrategy.FORWARD } 225 } 226 } 227 return { strategy: TouchTestStrategy.DEFAULT } 228 }) 229 } 230} 231``` 232 233 234 235### Example 3: Setting the Event Dispatch Strategy to DEFAULT 236 237In this example, dragging the blank area below the list will not scroll the list, and clicking the button will trigger its **onClick** event. 238 239```ts 240// xxx.ets 241import { promptAction } from '@kit.ArkUI'; 242 243@Entry 244@Component 245struct ListExample { 246 private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 247 @State text: string = 'Button' 248 249 build() { 250 Column() { 251 List({ space: 12, initialIndex: 0 }) { 252 ForEach(this.arr, (item: number) => { 253 ListItem() { 254 Text('Item ' + item) 255 .width('100%') 256 .height(56) 257 .fontSize(16) 258 .textAlign(TextAlign.Start) 259 }.borderRadius(24) 260 .backgroundColor(Color.White) 261 .padding({ left: 12, right: 12 }) 262 }, (item: string) => item) 263 } 264 .listDirection(Axis.Vertical) 265 .scrollBar(BarState.Off) 266 .edgeEffect(EdgeEffect.Spring) 267 .onScrollIndex((start: number, end: number) => { 268 console.info('first' + start) 269 console.info('last' + end) 270 }) 271 .onDidScroll((scrollOffset: number, scrollState: ScrollState) => { 272 console.info(`onScroll scrollState = ScrollState` + scrollState + `, scrollOffset = ` + scrollOffset) 273 }) 274 .width('100%') 275 .height('65%') 276 .id('MyList') 277 278 Button(this.text) 279 .width(312) 280 .height(40) 281 .id('Mybutton') 282 .fontSize(16) 283 .fontWeight(FontWeight.Medium) 284 .margin({ top: 80 }) 285 .onClick(() => { 286 this.text = 'click the button' 287 promptAction.showToast({ message: 'you click the button.', duration: 3000 }) 288 }) 289 } 290 .width('100%') 291 .height('100%') 292 .backgroundColor(0xF1F3F5) 293 .justifyContent(FlexAlign.End) 294 .padding({ left: 12, right: 12, bottom: 24 }) 295 .onChildTouchTest((touchinfo) => { 296 return { strategy: TouchTestStrategy.DEFAULT } 297 }) 298 } 299} 300``` 301 302 303