• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 自定义事件分发
2
3ArkUI在处理触屏事件时,会在触屏事件触发前进行按压点和组件区域的触摸测试,来收集需要响应触屏事件的组件,再基于触摸测试结果分发相应的触屏事件。在父节点,开发者可以通过onChildTouchTest决定如何让子节点去做触摸测试,影响子组件的触摸测试,最终影响后续的触屏事件分发,具体影响参考[TouchTestStrategy](#touchteststrategy枚举说明)枚举说明。
4
5>  **说明:**
6>
7>  - 从API Version 11开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
8>
9>  - onClick以及旋转、捏合手势经过自定义事件分发之后可能会因为触摸热区没有命中导致事件不响应。
10
11## onChildTouchTest
12
13onChildTouchTest(event: (value: Array<TouchTestInfo>) => TouchResult): T
14
15当前组件可通过设置回调来自定义子节点如何去做触摸测试。
16
17**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
18
19**系统能力:** SystemCapability.ArkUI.ArkUI.Full
20
21**参数:**
22
23| 参数名 | 类型                                       | 必填 | 说明                   |
24| ------ | ------------------------------------------ | ---- | ---------------------- |
25| value  | Array<[TouchTestInfo>](#touchtestinfo) | 是   | 包含子节点信息的数组。 |
26
27**返回值:**
28
29| 类型 | 说明 |
30| -------- | -------- |
31| T | 返回当前组件。 |
32
33>**说明:**
34>
35>子节点信息数组中只包含命名节点的信息,即开发者通过id属性设置了id的节点。
36
37## TouchTestInfo
38
39当前按压点所在组件的坐标系、id和尺寸相关信息。
40
41**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
42
43**系统能力:** SystemCapability.ArkUI.ArkUI.Full
44
45| 名称          | 类型   | 描述                                       |
46| ------------- | ------ | ---------------------------------------- |
47| windowX | number | 按压点相对于窗口左上角的x轴坐标。<br />单位:vp |
48| windowY   | number |按压点相对于窗口左上角的y轴坐标。<br />单位:vp|
49| parentX   | number |按压点相对于父组件左上角的x轴坐标。<br />单位:vp  |
50| parentY   | number |按压点相对于父组件左上角的y轴坐标。<br />单位:vp  |
51| x   | number | 按压点相对于子组件左上角的x轴坐标。<br />单位:vp |
52| y   | number | 按压点相对于子组件左上角的y轴坐标。<br />单位:vp |
53| rect   | [RectResult](ts-types.md#rectresult10) |子组件的大小。  |
54| [id](ts-universal-attributes-component-id.md)   | string | 通过id属性设置的组件id。 |
55
56## TouchResult
57
58自定义事件分发结果,开发者通过返回结果来影响事件分发。
59
60**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
61
62**系统能力:** SystemCapability.ArkUI.ArkUI.Full
63
64| 名称      | 类型                                     | 必填   | 描述                                |
65| --------- | --------- | ---- |--------------------------------------- |
66| strategy  | [TouchTestStrategy](#touchteststrategy枚举说明) | 是    | 事件派发策略。                     |
67| id  | string | 否    | 通过id属性设置的组件id。<br>当strategy为TouchTestStrategy.DEFAULT时,id是可选的;当strategy是TouchTestStrategy.FORWARD_COMPETITIONTouchTestStrategy.FORWARD时,id是必需的(如果没有返回id,则当成TouchTestStrategy.DEFAULT处理)。 |
68
69## TouchTestStrategy枚举说明
70
71事件派发策略。
72
73**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
74
75**系统能力:** SystemCapability.ArkUI.ArkUI.Full
76
77| 名称          | 描述                                       |
78| ------------| ----------------------------------------- |
79| DEFAULT     | 自定义分发不产生影响,系统按当前节点命中状态分发事件。 |
80| FORWARD_COMPETITION       | 应用指定分发事件到某个子节点,其他兄弟节点是否分发事件交由系统决定。 |
81| FORWARD | 应用指定分发事件到某个子节点,系统不再处理分发事件到其他兄弟节点。 |
82
83## 示例
84
85### 示例1(设置事件派发策略为FORWARD_COMPETITION)
86
87该示例点击List下方空白区域后拖动,能够拖动List滑动。点击Button按钮,Button会响应onClick事件。
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![onchildtouchtest](figures/on-child-touch-test-competition.gif)
158
159### 示例2(设置事件派发策略为FORWARD)
160
161点击List下方空白区域后拖动,能够拖动List滑动。点击Button按钮,Button不会响应onClick事件。
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![onchildtouchtest](figures/on-child-touch-test-forward.gif)
232
233### 示例3(设置事件派发策略为DEFAULT)
234
235点击List下方空白区域后拖动,List不会滑动。点击Button按钮,Button会响应onClick事件。
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![onchildtouchtest](figures/on-child-touch-test-default.gif)