Jetpack Compose поддерживает перетаскивание с помощью двух модификаторов:
dragAndDropSource– указывает, что в качестве начальной точки жеста перетаскивания используется компонуемый элемент.dragAndDropTarget: указывает на компонент, который принимает перетаскиваемые данные.
Например, чтобы пользователи могли перетаскивать изображение в вашем приложении, создайте composable-функцию image и добавьте модификатор dragAndDropSource. Чтобы настроить целевую область, создайте ещё один компонент изображения и добавьте модификатор dragAndDropTarget.
Модификаторы можно применять к нескольким источникам перетаскивания и нескольким целевым объектам.
Модификаторы позволяют приложениям обмениваться данными между двумя или более композициями с помощью ClipData, который совместим с реализациями View.
Как указать источник перетаскивания
Чтобы разрешить перетаскивание событий внутри компонента, добавьте модификатор dragAndDropSource.
В качестве параметра передается функция. Внутри этой функции используйте DragAndDropTransferData, чтобы представить передаваемые данные. Данные могут представлять собой удаленный URI, форматированный текст в буфере обмена, локальный файл и т. д., но все они должны быть заключены в объект ClipData. Укажите обычный текст, например:
Modifier.dragAndDropSource { _ -> DragAndDropTransferData( ClipData.newPlainText( "image Url", url ) ) }
Чтобы разрешить перетаскивание за границы приложения, конструктор DragAndDropTransferData принимает аргумент flags. В следующем примере константа DRAG_FLAG_GLOBAL указывает, что данные можно перетаскивать из одного приложения в другое:
Modifier.dragAndDropSource { _ -> DragAndDropTransferData( ClipData.newPlainText( "image Url", url ), flags = View.DRAG_FLAG_GLOBAL ) }
DragAndDropTransferData принимает флаги, поддерживаемые системой Android View.
Полный список доступных флагов можно найти в списке констант View.
Получение данных о дропах
Назначьте модификатор dragAndDropTarget composable-функции, чтобы она могла получать события перетаскивания. У модификатора два параметра: первый действует как фильтр и указывает, какие данные может принимать модификатор, а второй передает данные в обратном вызове.
Обратите внимание, что экземпляр функции обратного вызова должен быть запомнен. В следующем фрагменте кода показано, как запомнить обратный вызов:
val callback = remember { object : DragAndDropTarget { override fun onDrop(event: DragAndDropEvent): Boolean { // Parse received data return true } } }
Чтобы принимать данные от других приложений, используйте requestDragAndDropPermission, чтобы включить прием, и отпустите его, когда все будет готово:
val externalAppCallback = remember { object : DragAndDropTarget { override fun onDrop(event: DragAndDropEvent): Boolean { val permission = activity.requestDragAndDropPermissions(event.toAndroidDragEvent()) // Parse received data permission?.release() return true } } }
Важно помнить, что объект DragAndDropEvent, возвращаемый из обратного вызова Compose, отличается от объекта, ожидаемого методом requestDragAndDropPermission, поэтому перед передачей параметра в запрос разрешения необходимо вызвать для него функцию расширения toAndroidDragEvent().
В следующем фрагменте кода показано, как обрабатывать перетаскивание обычного текста:
Modifier.dragAndDropTarget( shouldStartDragAndDrop = { event -> event.mimeTypes().contains(ClipDescription.MIMETYPE_TEXT_PLAIN) }, target = callback // or externalAppCallback )
Функция обратного вызова должна возвращать значение true, если событие обработано, или false, если событие отклонено и не передается родительскому компоненту.
Как обрабатывать события перетаскивания
Переопределите обратные вызовы в интерфейсе DragAndDropTarget, чтобы отслеживать начало и конец события перетаскивания, а также вход и выход компонента. Это позволит вам точно управлять интерфейсом и поведением приложения.
object : DragAndDropTarget { override fun onStarted(event: DragAndDropEvent) { // When the drag event starts } override fun onEntered(event: DragAndDropEvent) { // When the dragged object enters the target surface } override fun onEnded(event: DragAndDropEvent) { // When the drag event stops } override fun onExited(event: DragAndDropEvent) { // When the dragged object exits the target surface } override fun onDrop(event: DragAndDropEvent): Boolean = true }
Дополнительные ресурсы
Практическая работа: Перетаскивание в Compose