Trascina

Jetpack Compose supporta il trascinamento con due modificatori:

Ad esempio, per consentire agli utenti di trascinare un'immagine nella tua app, crea un componibile di immagini e aggiungi il modificatore dragAndDropSource. Per impostare un target di rilascio, crea un'altra composizione di immagini e aggiungi il modificatore dragAndDropTarget.

I modificatori possono essere applicati a più origini di trascinamento e a più destinazioni di rilascio.

I modificatori consentono alle app di condividere dati tra due o più composabili utilizzando ClipData, che è interoperabile con le implementazioni di View.

Specifica un'origine di trascinamento

Per attivare gli eventi di trascinamento all'interno di un componente, aggiungi il modificatore dragAndDropSource. Questa funzione accetta una funzione come parametro. All'interno di questa funzione, utilizza DragAndDropTransferData per rappresentare i dati trasferibili. I dati possono essere un URI remoto, dati di testo avanzato negli appunti, un file locale e altro ancora, ma devono essere tutti racchiusi in un oggetto ClipData. Fornisci testo normale, ad esempio come segue:

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

Per consentire all'azione di trascinamento di superare i confini dell'app, il costruttore DragAndDropTransferData accetta un argomento flags. Nel seguente esempio, la costante DRAG_FLAG_GLOBAL specifica che i dati possono essere trascinati da un'app all'altra:

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

DragAndDropTransferData accetta i flag supportati dal sistema di visualizzazione Android. Consulta l'elenco delle costanti View per un elenco esaustivo dei flag disponibili.

Ricevere i dati sui cali

Assegna il modificatore dragAndDropTarget a un composable per consentirgli di ricevere eventi di trascinamento. Il modificatore ha due parametri: il primo funge da filtro e specifica il tipo di dati che può accettare, mentre il secondo invia i dati in un callback.

Tieni presente che l'istanza di callback deve essere memorizzata. Lo snippet riportato di seguito mostra come ricordare la chiamata di ritorno:

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

Per accettare i dati da altre app, usa requestDragAndDropPermission per attivare la ricezione e rilascia il pulsante al termine:

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

È importante ricordare che il valore DragAndDropEvent restituito dal callback Compose è diverso da quello previsto dal metodo requestDragAndDropPermission, pertanto devi chiamare la funzione di estensione toAndroidDragEvent() sul parametro prima di passarlo alla richiesta di autorizzazione.

Lo snippet seguente mostra come gestire il testo normale inserito:

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

La funzione di callback deve restituire true se l'evento viene utilizzato o false se l'evento viene rifiutato e non si propaga al componente principale.

Gestire gli eventi di trascinamento

Sostituisci i callback nell'interfaccia DragAndDropTarget per osservare quando un evento di trascinamento inizia, termina o entra o esce da un componente per un controllo preciso dell'interfaccia utente e del comportamento dell'app:

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
}

Risorse aggiuntive

Codelab: Trascina in Scrittura