1# 拖拽排序 2 3<!--Kit: ArkUI--> 4<!--Subsystem: ArkUI--> 5<!--Owner: @yylong--> 6<!--Designer: @yylong--> 7<!--Tester: @liuzhenshuo--> 8<!--Adviser: @HelloCrease--> 9 10在List组件下使用ForEach/LazyForEach/Repeat,并设置onMove事件,每次迭代生成一个ListItem时,可以使能拖拽排序。拖拽排序离手后,如果数据位置发生变化,将触发onMove事件,上报数据移动原始索引号和目标索引号。在onMove事件中,需要根据上报的起始索引号和目标索引号修改数据源。确保数据仅顺序发生变化,才能正常执行落位动画。 11 12> **说明:** 13> 14> 从API version 12开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 15 16## onMove 17 18onMove(handler: Optional\<OnMoveHandler\>): T 19 20拖拽排序数据移动回调。当父容器组件为[List](./ts-container-list.md),并且ForEach/LazyForEach/Repeat每次迭代都生成一个ListItem组件时才生效。设置拖拽排序时可以定义不同的拖拽操作,并在响应事件发生时响应。 21 22**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 23 24**系统能力:** SystemCapability.ArkUI.ArkUI.Full 25 26**参数:** 27 28| 参数名 | 类型 | 必填 | 说明 | 29| ------ | --------- | ---- | ---------- | 30| handler | Optional\<[OnMoveHandler](#onmovehandler)\> | 是 | 拖拽动作。 | 31 32**返回值:** 33 34| 类型 | 说明 | 35| ------ | --------- | 36| T | 返回当前组件。 | 37 38## onMove<sup>20+</sup> 39 40onMove(handler: Optional\<OnMoveHandler\>, eventHandler: ItemDragEventHandler): T 41 42拖拽排序数据移动回调。当父容器组件为[List](./ts-container-list.md),并且ForEach/LazyForEach/Repeat每次迭代都生成一个ListItem组件时才生效。设置拖拽排序时可以定义不同的拖拽操作,并在响应事件发生时响应。 43 44**原子化服务API:** 从API version 20开始,该接口支持在原子化服务中使用。 45 46**系统能力:** SystemCapability.ArkUI.ArkUI.Full 47 48**参数:** 49 50| 参数名 | 类型 | 必填 | 说明 | 51| ------ | --------- | ---- | ---------- | 52| handler | Optional\<[OnMoveHandler](#onmovehandler)\> | 是 | 拖拽动作。 | 53| eventHandler | [ItemDragEventHandler](#itemdrageventhandler20) | 是 | 拖拽发生时产生的回调。 | 54 55**返回值:** 56 57| 类型 | 说明 | 58| ------ | --------- | 59| T | 返回当前组件。 | 60 61## OnMoveHandler 62 63type OnMoveHandler = (from: number, to: number) => void 64 65定义数据源拖拽回调。 66 67**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 68 69**系统能力:** SystemCapability.ArkUI.ArkUI.Full 70 71**参数:** 72 73| 参数名 | 类型 | 必填 | 说明 | 74| ------ | --------- | ---- | ---------- | 75| from | number | 是 | 数据源拖拽起始索引号。取值范围是[0, 数据源长度-1]。 | 76| to | number | 是 | 数据源拖拽目标索引号。取值范围是[0, 数据源长度-1]。 | 77 78## ItemDragEventHandler<sup>20+</sup> 79 80定义数据源拖拽事件回调。用于响应不同的拖拽操作。 81 82**原子化服务API:** 从API version 20开始,该接口支持在原子化服务中使用。 83 84**系统能力:** SystemCapability.ArkUI.ArkUI.Full 85 86| 名称 | 类型 | 只读 | 可选 | 说明 | 87| ------ | ------ | ---- | ---- | -------------------- | 88| onLongPress | [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<number\> | 否 | 是 | 长按时触发的回调。<br>- 参数index为长按时当前目标的索引号。 | 89| onDragStart | [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<number\> | 否 | 是 | 在页面跟手滑动开始时触发的回调。<br>- 参数index为拖拽开始时当前目标的索引号。 | 90| onMoveThrough | [OnMoveHandler](#onmovehandler) | 否 | 是 | 在页面跟手滑动过程中经过其他组件时触发的回调。 | 91| onDrop | [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<number\> | 否 | 是 | 在页面跟手滑动结束时触发的回调。<br>- 参数index为拖拽结束时当前目标的索引号。 | 92 93## 示例 94 95### 示例1(使用OnMove进行拖拽) 96 97以下示例展示了ForEach在List组件内使用时的拖拽效果。 98 99```ts 100@Entry 101@Component 102struct ForEachSort { 103 @State arr: Array<string> = []; 104 105 build() { 106 Row() { 107 List() { 108 ForEach(this.arr, (item: string) => { 109 ListItem() { 110 Text(item.toString()) 111 .fontSize(16) 112 .textAlign(TextAlign.Center) 113 .size({height: 100, width: '100%'}) 114 }.margin(10) 115 .borderRadius(10) 116 .backgroundColor('#FFFFFFFF') 117 }, (item: string) => item) 118 .onMove((from:number, to:number) => { 119 let tmp = this.arr.splice(from, 1); 120 this.arr.splice(to, 0, tmp[0]); 121 }) 122 } 123 .width('100%') 124 .height('100%') 125 .backgroundColor('#FFDCDCDC') 126 } 127 } 128 aboutToAppear(): void { 129 for (let i = 0; i < 100; i++) { 130 this.arr.push(i.toString()); 131 } 132 } 133} 134``` 135 136### 示例2(使用OnMove进行拖拽,并设置拖拽事件回调) 137 138以下示例展示了ForEach在List组件设置拖拽效果后触发的回调事件。 139 140```ts 141// xxx.ets 142@Entry 143@Component 144struct ListOnMoveExample { 145 private arr: number[] = [0, 1, 2, 3, 4, 5, 6]; 146 147 build() { 148 Column() { 149 List({ space: 20, initialIndex: 0 }) { 150 ForEach(this.arr, (item: number) => { 151 ListItem() { 152 Text('第一个List' + item) 153 .width('100%') 154 .height(80) 155 .fontSize(16) 156 .textAlign(TextAlign.Center) 157 .borderRadius(10) 158 .backgroundColor(0xFFFFFF) 159 } 160 }, (item: string) => item) 161 .onMove((from: number, to: number) => { 162 let tmp = this.arr.splice(from, 1); 163 this.arr.splice(to, 0, tmp[0]); 164 console.info('List onMove From: ' + from); 165 console.info('List onMove To: ' + to); 166 }, 167 { 168 onLongPress: (index: number) => { 169 console.info('List onLongPress: ' + index); 170 }, 171 onDrop: (index: number) => { 172 console.info('List onDrop: ' + index); 173 }, 174 onDragStart: (index: number) => { 175 console.info('List onDragStart: ' + index); 176 }, 177 onMoveThrough: (from: number, to: number) => { 178 console.info('List onMoveThrough From: ' + from); 179 console.info('List onMoveThrough To: ' + to); 180 } 181 } 182 ) 183 }.width('90%') 184 .scrollBar(BarState.Off) 185 }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding({ top: 5 }) 186 } 187} 188```