Khung dựa trên bảng nhớ tạm của Android để sao chép và dán hỗ trợ các loại dữ liệu gốc và phức tạp, bao gồm:
- Chuỗi văn bản
- Cấu trúc dữ liệu phức tạp
- Dữ liệu luồng văn bản và nhị phân
- Thành phần ứng dụng
Dữ liệu văn bản đơn giản được lưu trữ trực tiếp trong bảng nhớ tạm, trong khi dữ liệu phức tạp được lưu trữ dưới dạng tham chiếu mà ứng dụng dán phân giải thông qua trình cung cấp nội dung.
Việc sao chép và dán diễn ra cả trong một ứng dụng và giữa các ứng dụng cài đặt khung.
Vì một phần của khung này sử dụng các nhà cung cấp nội dung, nên tài liệu này giả định rằng nhà phát triển biết về Android Content Provider API.
Làm việc với văn bản
Một số thành phần hỗ trợ sao chép và dán văn bản ra khỏi hộp, như minh hoạ trong bảng sau.
Thành phần | Đang sao chép văn bản | Dán văn bản |
---|---|---|
BasicTextField | ✅ | ✅ |
TextField | ✅ | ✅ |
Vùng chứa lựa chọn | ✅ |
Ví dụ: bạn có thể sao chép văn bản trong thẻ vào bảng nhớ tạm
trong đoạn mã sau và dán văn bản đã sao chép vào TextField
.
Bạn hiển thị trình đơn để dán văn bản bằng cách nhấn và giữ TextField
hoặc nhấn vào tay cầm con trỏ.
val textFieldState = rememberTextFieldState()
Column {
Card {
SelectionContainer {
Text("You can copy this text")
}
}
BasicTextField(state = textFieldState)
}
Bạn có thể dán văn bản bằng phím tắt sau: Ctrl+V . Phím tắt cũng có sẵn theo mặc định. Tham khảo phần Xử lý thao tác trên bàn phím để biết thông tin chi tiết.
Sao chép bằng ClipboardManager
Bạn có thể sao chép văn bản vào bảng nhớ tạm bằng ClipboardManager
.
Phương thức setText() của lớp này sao chép đối tượng Chuỗi đã truyền vào bảng nhớ tạm.
Đoạn mã sau đây sẽ sao chép "Hello, clipboard" (Xin chào, bảng nhớ tạm) vào bảng nhớ tạm khi người dùng nhấp vào nút.
// Retrieve a ClipboardManager object
val clipboardManager = LocalClipboardManager.current
Button(
onClick = {
// Copy "Hello, clipboard" to the clipboard
clipboardManager.setText("Hello, clipboard")
}
) {
Text("Click to copy a text")
}
Đoạn mã sau đây thực hiện tương tự, nhưng cung cấp cho bạn quyền kiểm soát chi tiết hơn.
Một trường hợp sử dụng phổ biến là sao chép nội dung nhạy cảm,
chẳng hạn như mật khẩu. ClipEntry
mô tả một mục trên bảng nhớ tạm.
Lớp này chứa đối tượng ClipData
mô tả dữ liệu trên bảng nhớ tạm.
Phương thức ClipData.newPlainText()
là một phương thức tiện lợi để tạo đối tượng ClipData
từ đối tượng Chuỗi.
Bạn có thể đặt đối tượng ClipEntry
đã tạo vào bảng nhớ tạm bằng cách gọi phương thức setClip() trên đối tượng ClipboardManager
.
// Retrieve a ClipboardManager object
val clipboardManager = LocalClipboardManager.current
Button(
onClick = {
val clipData = ClipData.newPlainText("plain text", "Hello, clipboard")
val clipEntry = ClipEntry(clipData)
clipboardManager.setClip(clipEntry)
}
) {
Text("Click to copy a text")
}
Dán bằng khay nhớ tạm quản lý
Bạn có thể truy cập văn bản đã sao chép vào bảng nhớ tạm
bằng cách gọi phương thức getText()
trong ClipboardManager
.
Phương thức getText()
của phương thức này trả về một đối tượng AnnotatedString
khi bạn sao chép văn bản vào bảng nhớ tạm.
Đoạn mã sau đây sẽ nối văn bản trong bảng nhớ tạm vào văn bản trong TextField
.
var textFieldState = rememberTextFieldState()
Column {
TextField(state = textFieldState)
Button(
onClick = {
// The getText method returns an AnnotatedString object or null
val annotatedString = clipboardManager.getText()
if(annotatedString != null) {
// The pasted text is placed on the tail of the TextField
textFieldState.edit {
append(text.toString())
}
}
}
) {
Text("Click to paste the text in the clipboard")
}
}
Làm việc với nội dung đa dạng thức
Người dùng thích hình ảnh, video và những nội dung biểu đạt khác.
Ứng dụng của bạn có thể cho phép người dùng sao chép nội dung đa dạng thức bằng
ClipboardManager
và ClipEntry
.
Đối tượng sửa đổi contentReceiver
giúp bạn triển khai tính năng dán nội dung đa dạng thức.
Sao chép nội dung đa dạng thức
Ứng dụng của bạn không thể sao chép nội dung đa dạng thức trực tiếp vào bảng nhớ tạm.
Thay vào đó, ứng dụng của bạn sẽ truyền một đối tượng URI
đến bảng nhớ tạm
và cung cấp quyền truy cập vào nội dung bằng ContentProvider
.
Đoạn mã sau đây cho biết cách sao chép hình ảnh JPEG vào bảng nhớ tạm.
Tham khảo bài viết Sao chép luồng dữ liệu để biết thông tin chi tiết.
// Get a reference to the context
val context = LocalContext.current
Button(
onClick = {
// URI of the copied JPEG data
val uri = Uri.parse("content://your.app.authority/0.jpg")
// Create a ClipData object from the URI value
// A ContentResolver finds a proper ContentProvider so that ClipData.newUri can set appropriate MIME type to the given URI
val clipData = ClipData.newUri(context.contentResolver, "Copied", uri)
// Create a ClipEntry object from the clipData value
val clipEntry = ClipEntry(clipData)
// Copy the JPEG data to the clipboard
clipboardManager.setClip(clipEntry)
}
) {
Text("Copy a JPEG data")
}
Dán nội dung đa dạng thức
Với đối tượng sửa đổi contentReceiver
, bạn có thể xử lý việc dán nội dung đa dạng thức
vào BasicTextField
trong thành phần đã sửa đổi.
Đoạn mã sau đây thêm URI được dán của dữ liệu hình ảnh
vào danh sách đối tượng Uri
.
// A URI list of images
val imageList by remember{ mutableListOf<Uri>() }
// Remember the ReceiveContentListener object as it is created inside a Composable scope
val receiveContentListener = remember {
ReceiveContentListener { transferableContent ->
// Handle the pasted data if it is image data
when {
// Check if the pasted data is an image or not
transferableContent.hasMediaType(MediaType.Image)) -> {
// Handle for each ClipData.Item object
// The consume() method returns a new TransferableContent object containging ignored ClipData.Item objects
transferableContent.consume { item ->
val uri = item.uri
if (uri != null) {
imageList.add(uri)
}
// Mark the ClipData.Item object consumed when the retrieved URI is not null
uri != null
}
}
// Return the given transferableContent when the pasted data is not an image
else -> transferableContent
}
}
}
val textFieldState = rememberTextFieldState()
BasicTextField(
state = textFieldState,
modifier = Modifier
.contentReceiver(receiveContentListener)
.fillMaxWidth()
.height(48.dp)
)
Đối tượng sửa đổi contentReceiver
lấy đối tượng ReceiveContentListener
làm đối số và gọi onReceive
của đối tượng được truyền khi người dùng dán dữ liệu
vào BasicTextField
bên trong thành phần được sửa đổi.
Đối tượng TransferableContent
được truyền đến phương thức onReceive. Phương thức này mô tả dữ liệu có thể được chuyển giữa các ứng dụng bằng cách dán trong trường hợp này.
Bạn có thể truy cập vào đối tượng ClipEntry
bằng cách tham chiếu đến thuộc tính clipEntry
.
Ví dụ: đối tượng ClipEntry
có thể có một số đối tượng ClipData.Item
khi người dùng chọn một số hình ảnh và sao chép các hình ảnh đó vào bảng nhớ tạm.
Bạn nên đánh dấu đã sử dụng hoặc bỏ qua cho từng đối tượng ClipData.Item
,
và trả về một TransferableContent
chứa
các đối tượng ClipData.Item
bị bỏ qua
để đối tượng sửa đổi contentReceiver
đối tượng cấp trên gần nhất có thể nhận được.
Phương thức TransferableContent.hasMediaType()
có thể giúp bạn xác định xem đối tượng TransferableContent
có thể cung cấp một mục có loại nội dung nghe nhìn hay không.
Ví dụ: lệnh gọi phương thức sau đây trả về true
nếu đối tượng TransferableContent
có thể cung cấp hình ảnh.
transferableContent.hasMediaType(MediaType.Image)
Làm việc với dữ liệu phức tạp
Bạn có thể sao chép dữ liệu phức tạp vào bảng nhớ tạm theo cách tương tự như cách bạn thực hiện đối với nội dung đa dạng thức. Hãy tham khảo bài viết Sử dụng trình cung cấp nội dung để sao chép dữ liệu phức tạp để biết thông tin chi tiết.
Bạn cũng có thể xử lý việc dán dữ liệu phức tạp
theo cách tương tự đối với nội dung đa dạng thức.
Bạn có thể nhận được URI của dữ liệu đã dán.
Bạn có thể truy xuất dữ liệu thực tế từ ContentProvider
.
Hãy tham khảo phần Truy xuất dữ liệu từ nhà cung cấp để biết thêm thông tin.
Ý kiến phản hồi về việc sao chép nội dung
Người dùng mong muốn nhận được phản hồi khi sao chép nội dung vào bảng nhớ tạm. Do đó, ngoài khung ứng dụng hỗ trợ thao tác sao chép và dán, Android sẽ hiển thị một giao diện người dùng mặc định cho người dùng khi sao chép trong Android 13 (API cấp 33) trở lên. Do tính năng này, có nguy cơ thông báo bị trùng lặp. Bạn có thể tìm hiểu thêm về trường hợp đặc biệt này trong phần Tránh thông báo trùng lặp.
Cung cấp phản hồi cho người dùng theo cách thủ công khi sao chép trong Android 12L (API cấp 32) trở xuống. Xem đề xuất.
Nội dung nhạy cảm
Nếu bạn chọn cho phép người dùng sao chép nội dung nhạy cảm vào bảng nhớ tạm, chẳng hạn như mật khẩu, thì ứng dụng của bạn phải cho hệ thống biết để hệ thống có thể tránh hiển thị nội dung nhạy cảm đã sao chép trong giao diện người dùng (hình 2).
Bạn phải thêm cờ vào ClipDescription
trong ClipData
trước khi gọi phương thức setClip()
trên đối tượng ClipboardManager
:
// If your app is compiled with the API level 33 SDK or higher.
clipData.apply {
description.extras = PersistableBundle().apply {
putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true)
}
}
// If your app is compiled with a lower SDK.
clipData.apply {
description.extras = PersistableBundle().apply {
putBoolean("android.content.extra.IS_SENSITIVE", true)
}
}