Kéo và thả

Jetpack Compose hỗ trợ tính năng kéo và thả bằng 2 đối tượng sửa đổi:

  • dragAndDropSource: Chỉ định một thành phần kết hợp làm điểm bắt đầu của cử chỉ kéo
  • dragAndDropTarget: Chỉ định một thành phần kết hợp chấp nhận dữ liệu được thả

Đối tượng sửa đổi cho phép ứng dụng chia sẻ dữ liệu giữa hai hoặc nhiều thành phần kết hợp bằng cách sử dụng ClipData (có thể tương tác với các phương thức triển khai View).

Bắt đầu một sự kiện kéo

Để bật các sự kiện kéo bên trong một thành phần, hãy thêm đối tượng sửa đổi dragAndDropSource. Đối tượng này sẽ lấy hàm tạm ngưng làm tham số. Hàm này xác định hoạt động tương tác của người dùng bắt đầu thao tác kéo. Đối tượng sửa đổi dragAndDropSource chờ cho đến khi nhận được sự kiện nhập con trỏ rồi thực thi lambda đã truyền đến trình xử lý sự kiện. Sử dụng hàm lambda để phát hiện nhiều sự kiện nhập, chẳng hạn như nhấn hoặc nhấn và giữ. Để biết thêm thông tin, hãy xem bài viết Phương thức nhập con trỏ trong Compose.

Sự kiện nhập con trỏ thường là thao tác nhấn và giữ được triển khai như sau:

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

Để bắt đầu phiên kéo và thả, hãy gọi hàm startTransfer(). Bên trong phạm vi này, hãy sử dụng DragAndDropTransferData để biểu thị dữ liệu có thể chuyển. Dữ liệu có thể là một URI từ xa, dữ liệu văn bản đa dạng thức trên bảng nhớ tạm, tệp cục bộ, v.v., nhưng tất cả đều cần được gói trong một đối tượng ClipData. Hãy cung cấp văn bản thuần tuý, chẳng hạn như sau:

Modifier.dragAndDropSource {
    detectTapGestures(onLongPress = {
        startTransfer(
            DragAndDropTransferData(
                ClipData.newPlainText(
                    "image Url", url
                )
            )
        )
    })
}

Để cho phép thao tác kéo qua các đường viền của ứng dụng, hàm khởi tạo DragAndDropTransferData sẽ chấp nhận đối số flags. Trong ví dụ sau, hằng số DRAG_FLAG_GLOBAL chỉ định rằng có thể kéo dữ liệu từ ứng dụng này sang ứng dụng khác:

Modifier.dragAndDropSource {
    detectTapGestures(onLongPress = {
        startTransfer(
            DragAndDropTransferData(
                ClipData.newPlainText(
                    "image Url", url
                ),
                flags = View.DRAG_FLAG_GLOBAL
            )
        )
    })
}

DragAndDropTransferData chấp nhận các cờ mà hệ thống Android View hỗ trợ. Xem danh sách hằng số View để biết danh sách đầy đủ các cờ có sẵn.

Nhận dữ liệu thả

Chỉ định đối tượng sửa đổi dragAndDropTarget cho một thành phần kết hợp để cho phép thành phần kết hợp đó nhận các sự kiện kéo và thả. Đối tượng sửa đổi có hai tham số: tham số đầu tiên đóng vai trò là bộ lọc và chỉ định loại dữ liệu mà đối tượng sửa đổi có thể chấp nhận, còn đối tượng thứ hai phân phối dữ liệu trong một lệnh gọi lại.

Xin lưu ý rằng bạn cần ghi nhớ thực thể của lệnh gọi lại. Đoạn mã sau đây cho biết cách ghi nhớ lệnh gọi lại:

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

Đoạn mã tiếp theo minh hoạ cách xử lý văn bản thuần tuý bị thả:

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

Hàm callback sẽ trả về true nếu sự kiện được sử dụng hoặc false nếu sự kiện bị từ chối và không truyền đến thành phần mẹ.

Xử lý các sự kiện kéo và thả

Ghi đè các lệnh gọi lại trong giao diện DragAndDropTarget để quan sát thời điểm một sự kiện kéo và thả bắt đầu, kết thúc hoặc vào/thoát khỏi một thành phần, nhằm kiểm soát chính xác giao diện người dùng và hành vi của ứng dụng:

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
}

Tài nguyên khác

Lớp học lập trình: Kéo và thả trong Compose