• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Drag-and-Drop Sorting
2
3By using **ForEach**, **LazyForEach**, or **Repeat** within a **List** component and setting up the **onMove** event, you can implement drag-and-drop sorting. When the drag-and-drop gesture is released, if any item's position changes, the **onMove** event is triggered, which reports the original index and target index of the relocated item. In the **onMove** event, the data source must be updated based on the reported start index and target index. Ensure that only the order of the data changes so that the drop animation can be executed properly.
4
5> **NOTE**
6>
7> The initial APIs of this module are supported since API version 12. Updates will be marked with a superscript to indicate their earliest API version.
8
9## onMove
10
11onMove(handler: Optional\<OnMoveHandler\>)
12
13Invoked when data is moved during drag-and-drop sorting. This callback is effective only when the parent container component is [List](./ts-container-list.md) and each iteration of **ForEach**, **LazyForEach**, or **Repeat** generates a **ListItem** component. It allows you to define custom drag actions and handle various drag events.
14
15**Atomic service API**: This API can be used in atomic services since API version 12.
16
17**System capability**: SystemCapability.ArkUI.ArkUI.Full
18
19**Parameters**
20
21| Name| Type     | Mandatory| Description      |
22| ------ | --------- | ---- | ---------- |
23| handler  | Optional\<[OnMoveHandler](#onmovehandler)\> | Yes  | Drag operation.|
24
25## onMove<sup>20+</sup>
26
27onMove(handler: Optional\<OnMoveHandler\>, eventHandler: ItemDragEventHandler)
28
29Invoked when data is moved during drag-and-drop sorting. This callback is effective only when the parent container component is [List](./ts-container-list.md) and each iteration of **ForEach**, **LazyForEach**, or **Repeat** generates a **ListItem** component. It allows you to define custom drag actions and handle various drag events.
30
31**Atomic service API**: This API can be used in atomic services since API version 20.
32
33**System capability**: SystemCapability.ArkUI.ArkUI.Full
34
35**Parameters**
36
37| Name| Type     | Mandatory| Description      |
38| ------ | --------- | ---- | ---------- |
39| handler  | Optional\<[OnMoveHandler](#onmovehandler)\> | Yes  | Drag operation.|
40| eventHandler  | [ItemDragEventHandler](#itemdrageventhandler20) | Yes  | Callback invoked when the drag occurs.|
41
42## OnMoveHandler
43
44type OnMoveHandler = (from: number, to: number) => void
45
46Defines the callback triggered when data is moved during drag-and-drop sorting.
47
48**Atomic service API**: This API can be used in atomic services since API version 12.
49
50**System capability**: SystemCapability.ArkUI.ArkUI.Full
51
52**Parameters**
53
54| Name| Type     | Mandatory| Description      |
55| ------ | --------- | ---- | ---------- |
56| from  | number | Yes  | Start index of the drag operation. The value range is [0, data source length - 1].|
57| to  | number | Yes  | End index of the drag operation. The value range is [0, data source length - 1].|
58
59## ItemDragEventHandler<sup>20+</sup>
60
61Defines callbacks for drag events on a data source, allowing you to respond to different drag operations.
62
63**Atomic service API**: This API can be used in atomic services since API version 20.
64
65**System capability**: SystemCapability.ArkUI.ArkUI.Full
66
67**Parameters**
68
69| Name| Type  | Mandatory| Description                |
70| ------ | ------ | ---- | -------------------- |
71| onLongPress  |  [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<number\> | No | Callback triggered when an item is long-pressed.<br>- **index**: index of the target when the long press occurs.|
72| onDragStart  | [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<number\> | No  | Callback triggered when dragging starts.<br>- **index**: index of the target when dragging starts.|
73| onMoveThrough  | [OnMoveHandler](#onmovehandler) | No  | Callback triggered when the dragged item moves over other items.|
74| onDrop  | [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<number\> | No  | Callback triggered when dragging ends.<br>- **index**: index of the target when dragging ends.|
75
76## Example
77
78### Example 1: Using onMove for Drag and Drop Operations
79
80This example demonstrates how to use **onMove** for drag and drop with **ForEach** in a **List** component.
81
82```ts
83@Entry
84@Component
85struct ForEachSort {
86  @State arr: Array<string> = [];
87
88  build() {
89    Row() {
90      List() {
91        ForEach(this.arr, (item: string) => {
92          ListItem() {
93            Text(item.toString())
94              .fontSize(16)
95              .textAlign(TextAlign.Center)
96              .size({height: 100, width: '100%'})
97          }.margin(10)
98          .borderRadius(10)
99          .backgroundColor('#FFFFFFFF')
100        }, (item: string) => item)
101          .onMove((from:number, to:number) => {
102            let tmp = this.arr.splice(from, 1);
103            this.arr.splice(to, 0, tmp[0]);
104          })
105      }
106      .width('100%')
107      .height('100%')
108      .backgroundColor('#FFDCDCDC')
109    }
110  }
111  aboutToAppear(): void {
112    for (let i = 0; i < 100; i++) {
113      this.arr.push(i.toString());
114    }
115  }
116}
117```
118
119### Example 2: Using onMove with Drag Event Callbacks
120
121This example demonstrates how to use **onMove** with additional drag event callbacks when **ForEach** is used in a **List** component.
122
123```ts
124// xxx.ets
125@Entry
126@Component
127struct ListOnMoveExample {
128  private arr: number[] = [0, 1, 2, 3, 4, 5, 6];
129
130  build() {
131    Column() {
132      List({ space: 20, initialIndex: 0 }) {
133        ForEach(this.arr, (item: number) => {
134          ListItem() {
135            Text('First list' + item)
136              .width('100%')
137              .height(80)
138              .fontSize(16)
139              .textAlign(TextAlign.Center)
140              .borderRadius(10)
141              .backgroundColor(0xFFFFFF)
142          }
143        }, (item: string) => item)
144          .onMove((from: number, to: number) => {
145            let tmp = this.arr.splice(from, 1);
146            this.arr.splice(to, 0, tmp[0]);
147            console.log('List onMove From: ' + from);
148            console.log('List onMove To: ' + to);
149          },
150            {
151              onLongPress: (index: number) => {
152                console.log('List onLongPress: ' + index);
153              },
154              onDrop: (index: number) => {
155                console.log('List onDrop: ' + index);
156              },
157              onDragStart: (index: number) => {
158                console.log('List onDragStart: ' + index);
159              },
160              onMoveThrough: (from: number, to: number) => {
161                console.log('List onMoveThrough From: ' + from);
162                console.log('List onMoveThrough To: ' + to);
163              }
164            }
165          )
166      }.width('90%')
167        .scrollBar(BarState.Off)
168    }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding({ top: 5 })
169  }
170}
171```
172