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
38## TouchTestInfo
39
40**Atomic service API**: This API can be used in atomic services since API version 12.
41
42**System capability**: SystemCapability.ArkUI.ArkUI.Full
43
44| Name         | Type  | Description                                      |
45| ------------- | ------ | ---------------------------------------- |
46| windowX | number | X coordinate of the touch point relative to the upper left corner of the window.|
47| windowY   | number |Y coordinate of the touch point relative to the upper left corner of the window.|
48| parentX   | number |X coordinate of the touch point relative to the upper left corner of the parent component. |
49| parentY   | number |Y coordinate of the touch point relative to the upper left corner of the parent component. |
50| x   | number | X coordinate of the touch point relative to the upper left corner of the child component.|
51| y   | number | Y coordinate of the touch point relative to the upper left corner of the child component.|
52| rect   | [RectResult](ts-types.md#rectresult10) |Size of the child component. |
53| [id](ts-universal-attributes-component-id.md)   | string | Component ID.|
54
55## TouchResult
56
57**Atomic service API**: This API can be used in atomic services since API version 12.
58
59**System capability**: SystemCapability.ArkUI.ArkUI.Full
60
61| Name     | Type                                    | Mandatory  | Description                               |
62| --------- | --------- | ---- |--------------------------------------- |
63| strategy  | [TouchTestStrategy](#touchteststrategy) | Yes   | Event dispatch strategy.                    |
64| 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.|
65
66## TouchTestStrategy
67
68**Widget capability**: This API can be used in ArkTS widgets since API version 11.
69
70**Atomic service API**: This API can be used in atomic services since API version 12.
71
72**System capability**: SystemCapability.ArkUI.ArkUI.Full
73
74| Name         | Description                                      |
75| ------------| ----------------------------------------- |
76| DEFAULT     | The default event dispatch mechanism for components is used.|
77| FORWARD_COMPETITION       | The event is dispatched to the specified child component, while the ArkUI touch test process is followed.|
78| FORWARD | The event is dispatched to the specified child component, and the ArkUI touch test process is not followed.|
79
80## Example
81
82### Example 1
83
84```ts
85// xxx.ets
86import { promptAction } from '@kit.ArkUI';
87
88@Entry
89@Component
90struct ListExample {
91  private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
92  @State text: string = 'Button'
93
94  build() {
95    Column() {
96      List({ space: 12, initialIndex: 0 }) {
97        ForEach(this.arr, (item: number) => {
98          ListItem() {
99            Text('Item ' + item)
100              .width('100%')
101              .height(56)
102              .fontSize(16)
103              .textAlign(TextAlign.Start)
104          }.borderRadius(24)
105          .backgroundColor(Color.White)
106          .padding({ left: 12, right: 12 })
107        }, (item: string) => item)
108      }
109      .listDirection(Axis.Vertical)
110      .scrollBar(BarState.Off)
111      .edgeEffect(EdgeEffect.Spring)
112      .onScrollIndex((start: number, end: number) => {
113        console.info('first' + start)
114        console.info('last' + end)
115      })
116      .onDidScroll((scrollOffset: number, scrollState: ScrollState) => {
117        console.info(`onScroll scrollState = ScrollState` + scrollState + `, scrollOffset = ` + scrollOffset)
118      })
119      .width('100%')
120      .height('65%')
121      .id('MyList')
122
123      Button(this.text)
124        .width(312)
125        .height(40)
126        .id('Mybutton')
127        .fontSize(16)
128        .fontWeight(FontWeight.Medium)
129        .margin({ top: 80 })
130        .onClick(() => {
131          this.text = 'click the button'
132          promptAction.showToast({ message: 'you click the button.', duration: 3000 })
133        })
134    }
135    .width('100%')
136    .height('100%')
137    .backgroundColor(0xF1F3F5)
138    .justifyContent(FlexAlign.End)
139    .padding({ left: 12, right: 12, bottom: 24 })
140    .onChildTouchTest((touchinfo) => {
141      for (let info of touchinfo) {
142        if (info.id == 'MyList') {
143          return { id: info.id, strategy: TouchTestStrategy.FORWARD_COMPETITION }
144        }
145      }
146      return { strategy: TouchTestStrategy.DEFAULT }
147    })
148  }
149}
150```
151After you touch the blank area in the lower part and drag the list, the list scrolls. After you touch the button, the button responds to the **onClick** event.
152
153![onchildtouchtest](figures/on-child-touch-test-competition.gif)
154
155### Example 2
156
157```ts
158// xxx.ets
159import { promptAction } from '@kit.ArkUI';
160
161@Entry
162@Component
163struct ListExample {
164  private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
165  @State text: string = 'Button'
166
167  build() {
168    Column() {
169      List({ space: 12, initialIndex: 0 }) {
170        ForEach(this.arr, (item: number) => {
171          ListItem() {
172            Text('Item ' + item)
173              .width('100%')
174              .height(56)
175              .fontSize(16)
176              .textAlign(TextAlign.Start)
177          }.borderRadius(24)
178          .backgroundColor(Color.White)
179          .padding({ left: 12, right: 12 })
180        }, (item: string) => item)
181      }
182      .listDirection(Axis.Vertical)
183      .scrollBar(BarState.Off)
184      .edgeEffect(EdgeEffect.Spring)
185      .onScrollIndex((start: number, end: number) => {
186        console.info('first' + start)
187        console.info('last' + end)
188      })
189      .onScroll((scrollOffset: number, scrollState: ScrollState) => {
190        console.info(`onScroll scrollState = ScrollState` + scrollState + `, scrollOffset = ` + scrollOffset)
191      })
192      .width('100%')
193      .height('65%')
194      .id('MyList')
195
196      Button(this.text)
197        .width(312)
198        .height(40)
199        .id('Mybutton')
200        .fontSize(16)
201        .fontWeight(FontWeight.Medium)
202        .margin({ top: 80 })
203        .onClick(() => {
204          this.text = 'click the button'
205          promptAction.showToast({ message: 'you click the button.', duration: 3000 })
206        })
207    }
208    .width('100%')
209    .height('100%')
210    .backgroundColor(0xF1F3F5)
211    .justifyContent(FlexAlign.End)
212    .padding({ left: 12, right: 12, bottom: 24 })
213    .onChildTouchTest((touchinfo) => {
214      for (let info of touchinfo) {
215        if (info.id == 'MyList') {
216          return { id: info.id, strategy: TouchTestStrategy.FORWARD }
217        }
218      }
219      return { strategy: TouchTestStrategy.DEFAULT }
220    })
221  }
222}
223```
224After you touch the blank area in the lower part and drag the list, the list scrolls. After you touch the button, the button does not respond to the **onClick** event.
225
226![onchildtouchtest](figures/on-child-touch-test-forward.gif)
227
228### Example 3
229
230```ts
231// xxx.ets
232import { promptAction } from '@kit.ArkUI';
233
234@Entry
235@Component
236struct ListExample {
237  private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
238  @State text: string = 'Button'
239
240  build() {
241    Column() {
242      List({ space: 12, initialIndex: 0 }) {
243        ForEach(this.arr, (item: number) => {
244          ListItem() {
245            Text('Item ' + item)
246              .width('100%')
247              .height(56)
248              .fontSize(16)
249              .textAlign(TextAlign.Start)
250          }.borderRadius(24)
251          .backgroundColor(Color.White)
252          .padding({ left: 12, right: 12 })
253        }, (item: string) => item)
254      }
255      .listDirection(Axis.Vertical)
256      .scrollBar(BarState.Off)
257      .edgeEffect(EdgeEffect.Spring)
258      .onScrollIndex((start: number, end: number) => {
259        console.info('first' + start)
260        console.info('last' + end)
261      })
262      .onScroll((scrollOffset: number, scrollState: ScrollState) => {
263        console.info(`onScroll scrollState = ScrollState` + scrollState + `, scrollOffset = ` + scrollOffset)
264      })
265      .width('100%')
266      .height('65%')
267      .id('MyList')
268
269      Button(this.text)
270        .width(312)
271        .height(40)
272        .id('Mybutton')
273        .fontSize(16)
274        .fontWeight(FontWeight.Medium)
275        .margin({ top: 80 })
276        .onClick(() => {
277          this.text = 'click the button'
278          promptAction.showToast({ message: 'you click the button.', duration: 3000 })
279        })
280    }
281    .width('100%')
282    .height('100%')
283    .backgroundColor(0xF1F3F5)
284    .justifyContent(FlexAlign.End)
285    .padding({ left: 12, right: 12, bottom: 24 })
286    .onChildTouchTest((touchinfo) => {
287      return { strategy: TouchTestStrategy.DEFAULT }
288    })
289  }
290}
291```
292After you touch the blank area in the lower part and drag the list, the list does not scroll. After you touch the button, the button responds to the **onClick** event.
293
294![onchildtouchtest](figures/on-child-touch-test-default.gif)
295