Jetpack Compose поддерживает перетаскивание с помощью двух модификаторов:
dragAndDropSource– указывает composable-функцию в качестве начальной точки жеста перетаскивания.dragAndDropTargetуказывает composable-функцию, которая принимает перетаскиваемые данные.
Например, чтобы пользователи могли перетаскивать изображение в приложении, создайте composable-функцию изображения и добавьте модификатор dragAndDropSource. Чтобы настроить цель перетаскивания, создайте ещё одну composable-функцию изображения и добавьте модификатор dragAndDropTarget.
Модификаторы можно применять к нескольким источникам перетаскивания и нескольким целям перетаскивания.
Модификаторы позволяют приложениям обмениваться данными между двумя или более composable-функциями с помощью 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