Jetpack Compose は、次の 2 つの修飾子によるドラッグ&ドロップをサポートしています。
dragAndDropSource: ドラッグ操作の開始点としてコンポーザブルを指定します。dragAndDropTarget: ドロップされたデータを受け入れるコンポーザブルを指定します。
たとえば、ユーザーがアプリ内で画像をドラッグできるようにするには、画像コンポーザブルを作成し、dragAndDropSource 修飾子を追加します。ドロップ ターゲットを設定するには、別の画像コンポーザブルを作成し、dragAndDropTarget 修飾子を追加します。
修飾子は、複数のドラッグソースと複数のドロップ ターゲットに適用できます。
修飾子を使用すると、アプリは ClipData を使用して 2 つ以上のコンポーザブル間でデータを共有できます。これは 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 修飾子をコンポーザブルに割り当てて、コンポーザブルがドラッグ&ドロップ イベントを受信できるようにします。この修飾子には 2 つのパラメータがあります。1 つ目はフィルタとして機能し、修飾子が受け入れ可能なデータの種類を指定します。2 つ目はコールバックでデータを配信します。
コールバック インスタンスは remember する必要があります。次のスニペットは、コールバックを記憶する方法を示しています。
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 } } }
Compose コールバックから返される DragAndDropEvent は、requestDragAndDropPermission メソッドが想定しているものとは異なることに注意してください。そのため、権限のリクエストに渡す前に、パラメータで toAndroidDragEvent() 拡張関数を呼び出す必要があります。
次のスニペットは、ドロップされた書式なしテキストを処理する方法を示しています。
Modifier.dragAndDropTarget( shouldStartDragAndDrop = { event -> event.mimeTypes().contains(ClipDescription.MIMETYPE_TEXT_PLAIN) }, target = callback // or externalAppCallback )
コールバック関数は、イベントが消費された場合は true を返し、イベントが拒否されて親コンポーネントに伝播しない場合は false を返す必要があります。
ドラッグ&ドロップ イベントを処理する
DragAndDropTarget インターフェースのコールバックをオーバーライドして、ドラッグ&ドロップ イベントが開始、終了、またはコンポーネントに入ったとき、コンポーネントから出たときを監視し、UI とアプリの動作を正確に制御します。
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 }
参考情報
Codelab: Compose でのドラッグ&ドロップ