compose-multiplatform
compose-multiplatform copied to clipboard
Will support drag and drop file into widget?
Will compose support drag and drop file into widget? Sometimes useful,for example, drag and drop an apk to the window to install it to phone.😉
https://github.com/JetBrains/compose-jb/issues/176
Thanks,but it will open a dialog. I mean we can drag and drop files directly from the Explorer to the window。🤔
Oh sorry. Compose itself won't support that. You can register for drap and drop events with DropTargetListener
on AppWindowAmbient.current
.
Here's a more concrete example https://twitter.com/tkuenneth/status/1331993022955917312?s=20 .
EDIT: https://dev.to/tkuenneth/from-swing-to-jetpack-compose-desktop-2-4a4h
🤔 It is based on the window. If I want to trigger in a specific area, I guess, this way could not be possible
By the way, thanks again
This link looks like what I want, thank you so much
There isn't an immediately obvious way to limit it to a specific area. I think it's worth leaving this issue open.
Maybe you can limit it with the new SwingPanel
.
Yeah, you are right. I only watch the video, he drop it in the widget, actually he doesnt limit it.
I thought about that idea, but in the latest「0.3.0-build136」
I think you need to use this version 0.0.0-unmerged-build21
.
Yeah, I see this version in issues, but I dont known how to find unmerged version.😉
by the way, this version ...
But this is another issues
You have to update the version in build.gradle
Yes, you are right🙌 Thanks a looooot
Guess we could close it, once SwingPanel support merged.
But wouldn’t it be better to let compose-jb support it?
bump still no support for file drag and drop on a single element instead of the entire window?
You can also embed a androidx.compose.ui.awt.SwingPanel
an have it accept drops, but that's also inconvenient to work with (and changes the style).
@felixdivo Yeah, compatibility with Swing is not compose's own behavior
You can also embed a
androidx.compose.ui.awt.SwingPanel
an have it accept drops
That also does not work nicely due to #1062 and (very importantly!) #1202. I thought about putting a compose UI in the drop traget by nesting a ComposePanel
in a SwingPanel
, but that also does not work due to #1060 and #1061.
You can do this with a custom modifier. Here's source for one here
Here's a desktop implementation.
And an Android implementation.
Here's a gif of both side by side
I have a number of use cases for this:
- Drag selected text from text views out into other apps
- Drag text from other apps into text views
- Drag images from other apps into text views
- Drag images from other apps into specific drop areas (similar to what previous example showed)
- Drag files from other apps (including file explorers) into specific drop areas
- Drag things between two slots in the same app (probably possible without using real dnd)
- Drag nodes from my app out into files
Hello everyone, thank you for your request and use cases! Experimental drag and drop functionality for desktop has been merged and will be available in the next dev builds. It allows moving files/images/text inside your Compose desktop application out of the box!
@Walingar this is great news! Is it available in 1.4.0?
Sample code for a text field receiving dropped text replacing the selection, working in desktop on v1.4.0.
Still missing the equivalent behaviour in the other direction.
var isDroppable by remember { mutableStateOf(false) }
val (textFieldValue, setTextFieldValue) = remember { mutableStateOf(TextFieldValue()) }
TextField(
value = textFieldValue,
onValueChange = setTextFieldValue,
modifier = Modifier
.border(4.dp, if (isDroppable) Color.Green else Color.Red)
.onExternalDrag(
onDragStart = { externalDragValue ->
isDroppable = externalDragValue.dragData is androidx.compose.ui.DragData.Text
},
onDragExit = {
isDroppable = false
},
onDrop = { externalDragValue ->
isDroppable = false
val dragData = externalDragValue.dragData
if (dragData is androidx.compose.ui.DragData.Text) {
setTextFieldValue(textFieldValue.copy(
text = textFieldValue.text.substring(0, textFieldValue.selection.start) +
dragData.readText() +
textFieldValue.text.substring(textFieldValue.selection.end),
selection = TextRange(textFieldValue.selection.end)
))
}
},
)
)
It works perfectly! Thanks @hakanai
@hakanai thank you for your example! Indeed, it is available in 1.4.0 as an experimental feature. So, please try it out and provide us feedback!
Also, @hakanai can you please describe your use case for DnD from Compose app. I will be glad if you can create a separate issue for that and describe it there!
What if I want to drop an image and send it somewhere as a file? How can I transform a Painter object to a file object?
`.onExternalDrag( onDragStart = { isDroppable = true }, onDragExit = { isDroppable = false }, onDrop = { externalDragValue -> isDroppable = false val dragData = externalDragValue.dragData if (dragData is androidx.compose.ui.DragData.Image) { val img = dragData.readImage()
}
}
)`
@June6-android You can try this code:
fun savePainterToFile(painter: Painter, file: File) {
val image: Image = painter.toAwtImage(Density(1f), LayoutDirection.Ltr)
val bufferedImage = BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB)
bufferedImage.graphics.drawImage(image, 0, 0, null);
ImageIO.write(bufferedImage, "png", file)
}
Currently im trying to disable/enable drag and drop for a widget using this modifier, but on runtime the component never gets recomposed to check for the drag data type
Is there any better way to do this?
kotlin var isDroppable by remember { mutableStateOf(false) } val dragModifier: Modifier = Modifier.onExternalDrag ( enabled = isDroppable, onDragStart = { val data = it.dragData isDroppable = data is DragData.FilesList } )