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