• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 拖拽事件
2
3拖拽事件指组件被长按后拖拽时触发的事件。
4
5>  **说明:**
6>
7>  从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
8
9## 事件
10
11| 名称                                                         | 支持冒泡 | 功能描述                                                     |
12| ------------------------------------------------------------ | -------- | ------------------------------------------------------------ |
13| onDragStart(event:&nbsp;(event?:&nbsp;[DragEvent](#dragevent说明),&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;&nbsp;[CustomBuilder](ts-types.md#custombuilder8) \| [DragItemInfo](#dragiteminfo说明)) | 否       | 第一次拖拽此事件绑定的组件时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。<br/>返回值:当前跟手效果所拖拽的对象,用于显示拖拽时的提示组件。<br/>长按150ms可触发拖拽事件。优先级:长按手势配置时间小于等于150ms时,长按手势优先触发,否则拖拽事件优先触发。 |
14| onDragEnter(event:&nbsp;(event?:&nbsp;[DragEvent](#dragevent说明),&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void) | 否       | 拖拽进入组件范围内时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。<br/>当监听了onDrop事件时,此事件才有效。 |
15| onDragMove(event:&nbsp;(event?:&nbsp;[DragEvent](#dragevent说明),&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void) | 否       | 拖拽在组件范围内移动时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。<br/>当监听了onDrop事件时,此事件才有效。 |
16| onDragLeave(event:&nbsp;(event?:&nbsp;[DragEvent](#dragevent说明),&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void) | 否       | 拖拽离开组件范围内时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。<br/>当监听了onDrop事件时,此事件才有效。 |
17| onDrop(event:&nbsp;(event?:&nbsp;[DragEvent](#dragevent说明),&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void) | 否       | 绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。 |
18
19## DragItemInfo说明
20
21| 名称      | 类型                                     | 必填   | 描述                                |
22| --------- | ---------------------------------------- | ---- | --------------------------------- |
23| pixelMap  | [PixelMap](../apis/js-apis-image.md#pixelmap7) | 否    | 设置拖拽过程中显示的图片。                     |
24| builder   | [CustomBuilder](ts-types.md#custombuilder8) | 否    | 拖拽过程中显示自定义组件,如果设置了pixelMap,则忽略此值。 |
25| extraInfo | string                                   | 否    | 拖拽项的描述。                           |
26
27
28## extraParams说明
29
30  用于返回组件在拖拽中需要用到的额外信息。
31
32  extraParams是Json对象转换的string字符串,可以通过Json.parse转换的Json对象获取如下属性。
33
34| 名称          | 类型   | 描述                                       |
35| ------------- | ------ | ---------------------------------------- |
36| selectedIndex | number | 当拖拽事件设在父容器的子元素时,selectedIndex表示当前被拖拽子元素是父容器第selectedIndex个子元素,selectedIndex从0开始。<br/>仅在ListItem组件的拖拽事件中生效。 |
37| insertIndex   | number | 当前拖拽元素在List组件中放下时,insertIndex表示被拖拽元素插入该组件的第insertIndex个位置,insertIndex从0开始。<br/>仅在List组件的拖拽事件中生效。 |
38
39## DragEvent说明
40
41| 名称     | 类型  | 描述             |
42| ------ | ------ | ---------------- |
43| getX() | number | 当前拖拽点相对于屏幕左上角的x轴坐标,单位为vp。 |
44| getY() | number | 当前拖拽点相对于屏幕左上角的y轴坐标,单位为vp。 |
45
46## 示例
47
48### 示例1
49
50```ts
51@Observed
52class ClassA {
53  public name: string
54  public bol: boolean
55
56  constructor(name: string, bol: boolean) {
57    this.name = name
58    this.bol = bol
59  }
60}
61
62@Extend(Text) function textStyle() {
63  .width('25%')
64  .height(35)
65  .fontSize(16)
66  .textAlign(TextAlign.Center)
67  .backgroundColor(0xAFEEEE)
68}
69
70@Entry
71@Component
72struct DragExample {
73  @State arr: ClassA[] = [new ClassA('A', true), new ClassA('B', true), new ClassA('C', true)]
74  @State dragIndex: number = 0
75
76  changeIndex(index1: number, index2: number) { // 交换数组位置
77    [this.arr[index1], this.arr[index2]] = [this.arr[index2], this.arr[index1]];
78  }
79
80  build() {
81    Column() {
82      Row({ space: 15 }) {
83        List({ space: 20 }) {
84          ForEach(this.arr, (item, index) => {
85            ListItem() {
86              Column() {
87                Child({ a: this.arr[index] })
88              }
89              .onTouch((event: TouchEvent) => {
90                if (event.type === TouchType.Down) {
91                  this.dragIndex = index // 获取当前拖拽子组件的索引
92                  console.info('onTouch' + this.dragIndex)
93                }
94              })
95            }
96          })
97        }
98        .listDirection(Axis.Horizontal)
99        .onDrop((event: DragEvent, extraParams: string) => { // 绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。
100          let jsonString = JSON.parse(extraParams);
101          this.changeIndex(this.dragIndex, jsonString.insertIndex)
102        })
103      }.padding({ top: 10, bottom: 10 }).margin(10)
104
105    }.width('100%').height('100%').padding({ top: 20 }).margin({ top: 20 })
106  }
107}
108
109@Component
110struct Child {
111  @ObjectLink a: ClassA
112
113  @Builder pixelMapBuilder() {
114    Column() {
115      Text(this.a.name)
116        .width('50%')
117        .height(60)
118        .fontSize(16)
119        .borderRadius(10)
120        .textAlign(TextAlign.Center)
121        .backgroundColor(Color.Yellow)
122    }
123  }
124
125  build() {
126    Column() {
127      Text(this.a.name)
128        .textStyle()
129        .visibility(this.a.bol ? Visibility.Visible : Visibility.None)
130        .onDragStart(() => { // 第一次拖拽此事件绑定的组件时,触发回调。
131          this.a.bol = false // 控制显隐
132          return this.pixelMapBuilder() // 设置拖拽过程中显示的图片。
133        })
134        .onTouch((event: TouchEvent) => {
135          if (event.type === TouchType.Up) {
136            this.a.bol = true
137          }
138        })
139      Text('')
140        .width('25%')
141        .height(35)
142        .fontSize(16)
143        .textAlign(TextAlign.Center)
144        .border({ width: 5, color: 'red' })
145        .visibility(!this.a.bol ? Visibility.Visible : Visibility.None)
146    }
147  }
148}
149```
150
151![drag-drop](figures/drag-drop.gif)
152
153### 示例2
154
155```ts
156// xxx.ets
157@Extend(Text) function textStyle () {
158  .width('25%')
159  .height(35)
160  .fontSize(16)
161  .textAlign(TextAlign.Center)
162  .backgroundColor(0xAFEEEE)
163}
164
165@Entry
166@Component
167struct DragExample {
168  @State numbers: string[] = ['one', 'two', 'three', 'four', 'five', 'six']
169  @State text: string = ''
170  @State bool: boolean = true
171  @State eventType: string = ''
172  @State appleVisible: Visibility = Visibility.Visible
173  @State orangeVisible: Visibility = Visibility.Visible
174  @State bananaVisible: Visibility = Visibility.Visible
175  private dragList: string[] = ['apple', 'orange', 'banana']
176  @State fruitVisible: Visibility[] = [Visibility.Visible, Visibility.Visible, Visibility.Visible]
177  @State idx: number = 0
178
179  // 自定义拖拽过程中显示的内容
180  @Builder pixelMapBuilder() {
181    Column() {
182      Text(this.text)
183        .width('50%')
184        .height(60)
185        .fontSize(16)
186        .borderRadius(10)
187        .textAlign(TextAlign.Center)
188        .backgroundColor(Color.Yellow)
189    }
190  }
191
192  build() {
193    Column() {
194      Text('There are three Text elements here')
195        .fontSize(12)
196        .fontColor(0xCCCCCC)
197        .width('90%')
198        .textAlign(TextAlign.Start)
199        .margin(5)
200      Row({ space: 15 }) {
201        ForEach(this.dragList, (item, index) => {
202          Text(item)
203            .textStyle()
204            .visibility(this.fruitVisible[index])
205            .onDragStart(() => {
206              this.bool = true
207              this.text = item
208              this.fruitVisible[index] = Visibility.None
209              return this.pixelMapBuilder
210            })
211            .onTouch((event: TouchEvent) => {
212              if (event.type === TouchType.Down) {
213                this.eventType = 'Down'
214                this.idx = index
215              }
216              if (event.type === TouchType.Up) {
217                this.eventType = 'Up'
218                if (this.bool) {
219                  this.fruitVisible[index] = Visibility.Visible
220                }
221              }
222            })
223        })
224      }.padding({ top: 10, bottom: 10 }).margin(10)
225
226      Text('This is a List element')
227        .fontSize(12)
228        .fontColor(0xCCCCCC)
229        .width('90%')
230        .textAlign(TextAlign.Start)
231        .margin(15)
232      List({ space: 20 }) {
233        ForEach(this.numbers, (item) => {
234          ListItem() {
235            Text(item)
236              .width('100%')
237              .height(80)
238              .fontSize(16)
239              .borderRadius(10)
240              .textAlign(TextAlign.Center)
241              .backgroundColor(0xAFEEEE)
242          }
243        }, item => item)
244      }
245      .editMode(true)
246      .height('50%')
247      .width('90%')
248      .border({ width: 1 })
249      .padding(15)
250      .divider({ strokeWidth: 2, color: 0xFFFFFF, startMargin: 20, endMargin: 20 })
251      .onDragEnter((event: DragEvent, extraParams: string) => {
252        console.log('List onDragEnter, ' + extraParams + 'X:' + event.getX() + 'Y:' + event.getY())
253      })
254      .onDragMove((event: DragEvent, extraParams: string) => {
255        console.log('List onDragMove, ' + extraParams + 'X:' + event.getX() + 'Y:' + event.getY())
256      })
257      .onDragLeave((event: DragEvent, extraParams: string) => {
258        console.log('List onDragLeave, ' + extraParams + 'X:' + event.getX() + 'Y:' + event.getY())
259      })
260      .onDrop((event: DragEvent, extraParams: string) => {
261        let jsonString = JSON.parse(extraParams);
262        if (this.bool) {
263          // 通过splice方法插入元素
264          this.numbers.splice(jsonString.insertIndex, 0, this.text)
265          this.bool = false
266        }
267        this.fruitVisible[this.idx] = Visibility.None
268      })
269    }.width('100%').height('100%').padding({ top: 20 }).margin({ top: 20 })
270  }
271}
272```
273
274![zh-cn_image_0000001252667389](figures/zh-cn_image_0000001252667389.gif)
275