Przeciągnij i upuść

Jetpack Compose obsługuje przeciąganie i upuszczanie za pomocą 2 modyfikatorów:

  • dragAndDropSource: określa element kompozycyjny jako punkt początkowy gestu przeciągania.
  • dragAndDropTarget: określa element kompozycyjny, który akceptuje upuszczone dane.

Aby na przykład umożliwić użytkownikom przeciąganie obrazu w aplikacji, utwórz funkcję kompozycyjną obrazu i dodaj modyfikator dragAndDropSource. Aby skonfigurować miejsce upuszczenia, utwórz kolejną funkcję kompozycyjną obrazu i dodaj modyfikator dragAndDropTarget.

Modyfikatory można stosować do wielu źródeł przeciągania i wielu miejsc docelowych upuszczania.

Modyfikatory umożliwiają aplikacjom udostępnianie danych między co najmniej 2 komponentami za pomocą ClipData, który współdziała z implementacjami View.

Określanie źródła przeciągania

Aby włączyć zdarzenia przeciągania w komponencie, dodaj modyfikator dragAndDropSource. Ta funkcja przyjmuje funkcję jako parametr. W tej funkcji użyj DragAndDropTransferData, aby reprezentować dane, które można przenieść. Dane mogą być zdalnym identyfikatorem URI, tekstem sformatowanym w schowku, plikiem lokalnym lub innym elementem, ale wszystkie muszą być opakowane w obiekt ClipData. Podaj zwykły tekst, na przykład w ten sposób:

Modifier.dragAndDropSource { _ ->
    DragAndDropTransferData(
        ClipData.newPlainText(
            "image Url", url
        )
    )
}

Aby umożliwić przeciąganie poza granice aplikacji, konstruktor DragAndDropTransferData akceptuje argument flags. W tym przykładzie stała DRAG_FLAG_GLOBAL określa, że dane można przeciągać z jednej aplikacji do drugiej:

Modifier.dragAndDropSource { _ ->
    DragAndDropTransferData(
        ClipData.newPlainText(
            "image Url", url
        ),
        flags = View.DRAG_FLAG_GLOBAL
    )
}

DragAndDropTransferData akceptuje flagi obsługiwane przez system Android View. Pełną listę dostępnych flag znajdziesz na liście stałych View.

Odbieranie danych o upuszczeniu

Przypisz modyfikator dragAndDropTarget do funkcji kompozycyjnej, aby umożliwić jej odbieranie zdarzeń przeciągania i upuszczania. Modyfikator ma 2 parametry: pierwszy działa jako filtr i określa rodzaj danych, które modyfikator może akceptować, a drugi dostarcza dane w wywołaniu zwrotnym.

Pamiętaj, że instancja wywołania zwrotnego powinna być zapamiętana. Poniższy fragment kodu pokazuje, jak zapamiętać wywołanie zwrotne:

val callback = remember {
    object : DragAndDropTarget {
        override fun onDrop(event: DragAndDropEvent): Boolean {
            // Parse received data
            return true
        }
    }
}

Aby akceptować dane z innych aplikacji, użyj requestDragAndDropPermission, aby włączyć odbiór, i zwolnij, gdy skończysz:

val externalAppCallback = remember {
    object : DragAndDropTarget {
        override fun onDrop(event: DragAndDropEvent): Boolean {
            val permission =
                activity.requestDragAndDropPermissions(event.toAndroidDragEvent())
            // Parse received data
            permission?.release()
            return true
        }
    }
}

Pamiętaj, że obiekt DragAndDropEvent zwracany przez wywołanie zwrotne Compose różni się od obiektu oczekiwanego przez metodę requestDragAndDropPermission, dlatego przed przekazaniem parametru do prośby o uprawnienia musisz wywołać funkcję rozszerzenia toAndroidDragEvent().

Poniższy fragment kodu pokazuje, jak obsługiwać upuszczony zwykły tekst:

Modifier.dragAndDropTarget(
    shouldStartDragAndDrop = { event ->
        event.mimeTypes().contains(ClipDescription.MIMETYPE_TEXT_PLAIN)
    }, target = callback // or externalAppCallback
)

Funkcja wywołania zwrotnego powinna zwracać wartość true, jeśli zdarzenie zostało wykorzystane, lub false, jeśli zdarzenie zostało odrzucone i nie zostało przekazane do komponentu nadrzędnego.

Obsługa zdarzeń przeciągania i upuszczania

Zastąp wywołania zwrotne w interfejsie DragAndDropTarget, aby obserwować, kiedy zdarzenie przeciągania i upuszczania się rozpoczyna, kończy lub wchodzi do komponentu albo go opuszcza. Pozwoli to na precyzyjne kontrolowanie interfejsu i zachowania aplikacji:

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
}

Dodatkowe materiały

Ćwiczenie w Codelabs: przeciągnij i upuść w Compose