Przeciągnij i upuść

Jetpack Compose obsługuje przeciąganie i upuszczanie z użyciem dwóch modyfikatorów:

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

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

Rozpoczynanie wydarzenia przeciągania

Aby włączyć zdarzenia przeciągania wewnątrz komponentu, dodaj modyfikator dragAndDropSource, który przyjmuje funkcję zawieszania jako parametr. Ta funkcja określa interakcję użytkownika, która rozpoczyna operację przeciągania. Modyfikator dragAndDropSource czeka, aż otrzyma zdarzenie wejściowe wskaźnika, a następnie wykonuje polecenie lambda przekazane do modułu obsługi zdarzeń. Funkcja lambda służy do wykrywania różnych zdarzeń wejściowych, np. dotknięcia lub przytrzymania. Więcej informacji znajdziesz w sekcji Wprowadzanie wskaźnika w sekcji Tworzenie.

Zdarzenie danych wejściowych wskaźnika to zwykle długie naciśnięcie zaimplementowane w ten sposób:

Modifier.dragAndDropSource {
    detectTapGestures(onLongPress = {
        // Transfer data here.
    })
}

Aby rozpocząć sesję przeciągania i upuszczania, wywołaj funkcję startTransfer(). Poza tym zakresem dane, które można przenieść, reprezentują wartość DragAndDropTransferData. Może to być zdalny identyfikator URI, dane tekstowe w schowku, plik lokalny itp., ale wszystkie te dane muszą być umieszczone w obiekcie ClipData. Wpisz zwykły tekst, na przykład:

Modifier.dragAndDropSource {
    detectTapGestures(onLongPress = {
        startTransfer(
            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 {
    detectTapGestures(onLongPress = {
        startTransfer(
            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 spadku

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

Pamiętaj, że instancja wywołania zwrotnego powinna być zapamiętana. Ten 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
        }
    }
}

Następny fragment pokazuje, jak postępować z porzuconym zwykłym tekstem:

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

Funkcja wywołania zwrotnego powinna zwrócić wartość true, jeśli zdarzenie zostanie wywołane, lub false, jeśli zdarzenie zostanie odrzucone i nie zostanie rozpowszechnione w komponencie nadrzędnym.

Obsługa zdarzeń przeciągania i upuszczania

Zastępuj wywołania zwrotne w interfejsie DragAndDropTarget, aby obserwować, kiedy zdarzenie przeciągania i upuszczania rozpoczyna, kończy się lub pojawia się w komponencie albo je zamyka, co pozwala na dokładną kontrolę interfejsu i działania 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

Ćwiczenia z programowania: przeciąganie i upuszczanie w obszarze Utwórz