1# Drag and Drop Control 2 3The drag and drop control attributes set whether a component can respond to drag events. 4 5> **NOTE** 6> 7> The APIs of this module are supported since API version 10. Updates will be marked with a superscript to indicate their earliest API version. 8 9The ArkUI framework implements the drag and drop capability for the following components, allowing them to serve as the drag source (from which data can be dragged) or drop target (to which data can be dropped). To enable drag and drop for these components, you only need to set their **draggable** attribute to **true**. 10 11- The following component supports drag actions by default: **\<Search>**, **\<TextInput>**, **\<TextArea>**, **\<RichEditor>**, **\<Text>**, **\<Image>**, **\<FormComponent>**, **\<Hyperlink>** 12 13- The following component supports drop actions by default: **\<Search>**, **\<TextInput>**, **\<TextArea>**, **\<Video>** 14 15You can also define drag responses by implementing common drag events. 16 17To enable drag and drop for other components, you need to set the **draggable** attribute to **true** and implement data transmission in APIs such as **onDragStart**. 18 19## allowDrop 20 21allowDrop(value: Array<UniformDataType>) 22 23Type of data that can be dropped to the component. 24 25**System capability**: SystemCapability.ArkUI.ArkUI.Full 26 27**Parameters** 28 29| Name| Type | Mandatory| Description | 30| ------ | ------------------------------------------------------------ | ---- | ----------------------------------------------- | 31| value | Array\<[UniformDataType](../apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype)> | Yes | Type of data that can be dropped to the component.<br>Default value: empty| 32 33## draggable 34 35draggable(value: boolean) 36 37Whether the component is draggable. 38 39**System capability**: SystemCapability.ArkUI.ArkUI.Full 40 41**Parameters** 42 43| Name| Type | Mandatory| Description | 44| ------ | ------- | ---- | ---------------------------------------------- | 45| value | boolean | Yes | Whether the component is draggable.<br>Default value: **false**| 46 47## dragPreview<sup>11+</sup> 48 49dragPreview(value: CustomBuilder | DragItemInfo) 50 51Sets the preview displayed when the component is dragged 52 53**System capability**: SystemCapability.ArkUI.ArkUI.Full 54 55**Parameters** 56 57| Name| Type | Mandatory| Description | 58| ------ | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 59| value | [CustomBuilder](ts-types.md#custombuilder8) \| [DragItemInfo](ts-universal-events-drag-drop.md#dragiteminfo) | Yes | Preview displayed when the component is dragged. This attribute has effect for **onDragStart** only.<br>If the component supports drag and drop and a preview is specified through [bindContextMenu](ts-universal-attributes-menu.md#bindcontextmenu8), that specified preview is displayed when the component is dragged. The priority of the background image returned in [onDragStart](ts-universal-events-drag-drop.md#ondragstart) is lower than that of the preview set in [dragPreview](ts-universal-attributes-drag-drop.md#dragpreview11). This means that, once set, the latter will be used in place of the former. Because [CustomBuilder](ts-types.md#custombuilder8) can be used only after offline rendering, it may increase performance overhead and latency. In light of this, you are advised to use [PixelMap](../apis/js-apis-image.md#pixelmap7) in [DragItemInfo](ts-universal-events-drag-drop.md#dragiteminfo) to set the preview.<br>Default value: empty<br>| 60 61## dragPreviewOptions<sup>11+</sup> 62 63dragPreviewOptions(value: DragPreviewOptions) 64 65Sets how the drag preview is processed when the component is dragged. This API works only for **onDragStart**. 66 67**System capability**: SystemCapability.ArkUI.ArkUI.Full 68 69**Parameters** 70 71| Name| Type | Mandatory| Description | 72| ------ | --------------------------------------------------------- | ---- | ------------------------------------------------------------ | 73| value | [DragPreviewOptions](#dragpreviewoptions11)<sup>11+</sup> | Yes | How the drag preview is processed when the component is dragged.<br>Default value: empty| 74 75## DragPreviewOptions<sup>11+</sup> 76 77| Name| Type| Mandatory| Description| 78| -------- | -------- | -------- | -------- | 79| mode | [DragPreviewMode](#dragpreviewmode11) | No| How the background image is processed when the component is dragged.<br>Default value: **DragPreviewMode.AUTO**<br>| 80 81## DragPreviewMode<sup>11+</sup> 82 83| Name| Value| Description| 84| -------- | ------- | -------- | 85| AUTO | 0 | The system automatically changes the position of the dragged point based on the scenario and automatically scales the background image based on set rules.| 86| DISABLE_SCALE | 1 | The system does not scale the background image.| 87 88## Example 89### Example 1 90Example of using the **allowDrop** and **draggable** attributes: 91 92```ts 93// xxx.ets 94import UDC from '@ohos.data.unifiedDataChannel'; 95import UTD from '@ohos.data.uniformTypeDescriptor'; 96 97@Entry 98@Component 99struct ImageExample { 100 @State uri: string = "" 101 @State AblockArr: string[] = [] 102 @State BblockArr: string[] = [] 103 @State AVisible: Visibility = Visibility.Visible 104 @State dragSuccess :Boolean = false 105 106 build() { 107 Column() { 108 Text ('Image drag and drop') 109 .fontSize('30dp') 110 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceAround }) { 111 Image($r('app.media.icon')) 112 .width(100) 113 .height(100) 114 .border({ width: 1 }) 115 .visibility(this.AVisible) 116 .draggable(true) 117 .onDragEnd((event: DragEvent) => { 118 let ret = event.getResult(); 119 if(ret == 0) { 120 console.log("enter ret == 0") 121 this.AVisible = Visibility.Hidden; 122 } else { 123 console.log("enter ret != 0") 124 this.AVisible = Visibility.Visible; 125 } 126 }) 127 } 128 .margin({ bottom: 20 }) 129 Row() { 130 Column(){ 131 Text('Invalid drop target') 132 .fontSize('15dp') 133 .height('10%') 134 List(){ 135 ForEach(this.AblockArr, (item:string, index) => { 136 ListItem() { 137 Image(item) 138 .width(100) 139 .height(100) 140 .border({width: 1}) 141 } 142 .margin({ left: 30 , top : 30}) 143 }, (item:string) => item) 144 } 145 .height('90%') 146 .width('100%') 147 .allowDrop([UTD.UniformDataType.TEXT]) 148 .onDrop((event?: DragEvent, extraParams?: string) => { 149 this.uri = JSON.parse(extraParams as string).extraInfo; 150 this.AblockArr.splice(JSON.parse(extraParams as string).insertIndex, 0, this.uri); 151 console.log("ondrop not udmf data"); 152 }) 153 .border({width: 1}) 154 } 155 .height("50%") 156 .width("45%") 157 .border({ width: 1 }) 158 .margin({ left: 12 }) 159 Column(){ 160 Text ('Valid drop target') 161 .fontSize('15dp') 162 .height('10%') 163 List(){ 164 ForEach(this.BblockArr, (item:string, index) => { 165 ListItem() { 166 Image(item) 167 .width(100) 168 .height(100) 169 .border({width: 1}) 170 } 171 .margin({ left: 30 , top : 30}) 172 }, (item:string) => item) 173 } 174 .border({width: 1}) 175 .height('90%') 176 .width('100%') 177 .allowDrop([UTD.UniformDataType.IMAGE]) 178 .onDrop((event?: DragEvent, extraParams?: string) => { 179 console.log("enter onDrop") 180 let dragData:UnifiedData = (event as DragEvent).getData() as UnifiedData; 181 if(dragData != undefined) { 182 let arr:Array<UDC.UnifiedRecord> = dragData.getRecords(); 183 if(arr.length > 0) { 184 let image = arr[0] as UDC.Image; 185 this.uri = image.imageUri; 186 this.BblockArr.splice(JSON.parse(extraParams as string).insertIndex, 0, this.uri); 187 } else { 188 console.log(`dragData arr is null`) 189 } 190 } else { 191 console.log(`dragData is undefined`) 192 } 193 console.log("ondrop udmf data"); 194 this.dragSuccess = true 195 }) 196 } 197 .height("50%") 198 .width("45%") 199 .border({ width: 1 }) 200 .margin({ left: 12 }) 201 } 202 }.width('100%') 203 } 204} 205``` 206 207 208 209 210 211 212 213### Example 2 214Example of using the **dragPreview** attribute: 215```ts 216// xxx.ets 217@Entry 218@Component 219struct DragPreviewDemo{ 220 @Builder dragPreviewBuilder() { 221 Column() { 222 Text("dragPreview") 223 .width(150) 224 .height(50) 225 .fontSize(20) 226 .borderRadius(10) 227 .textAlign(TextAlign.Center) 228 .fontColor(Color.Black) 229 .backgroundColor(Color.Pink) 230 } 231 } 232 233 @Builder MenuBuilder() { 234 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 235 Text("menu item 1") 236 .fontSize(15) 237 .width(100) 238 .height(40) 239 .textAlign(TextAlign.Center) 240 .fontColor(Color.Black) 241 .backgroundColor(Color.Pink) 242 Divider() 243 .height(5) 244 Text("menu item 2") 245 .fontSize(15) 246 .width(100) 247 .height(40) 248 .textAlign(TextAlign.Center) 249 .fontColor(Color.Black) 250 .backgroundColor(Color.Pink) 251 } 252 .width(100) 253 } 254 255 build() { 256 Row() { 257 Column() { 258 Image('/resource/image.jpeg') 259 .width("30%") 260 .draggable(true) 261 .bindContextMenu(this.MenuBuilder, ResponseType.LongPress) 262 .onDragStart(() => { 263 console.log("Image onDragStart") 264 }) 265 .dragPreview(this.dragPreviewBuilder) 266 } 267 .width("100%") 268 } 269 .height("100%") 270 } 271} 272``` 273 274 275 276### Example 3 277Example of using the **dragPreviewOptions** attribute: 278```ts 279// xxx.ets 280@Entry 281@Component 282struct dragPreviewOptionsDemo{ 283 build() { 284 Row() { 285 Column() { 286 Image('/resource/image.jpeg') 287 .margin({ top: 10 }) 288 .width("100%") 289 .draggable(true) 290 .dragPreviewOptions({ mode: DragPreviewMode.AUTO }) 291 } 292 .width("100%") 293 .height("100%") 294 } 295 } 296} 297``` 298 299 300