Framework berbasis papan klip Android untuk menyalin dan menempel mendukung jenis data primitif dan kompleks, termasuk:
- String teks
- Struktur data yang kompleks
- Data aliran teks dan biner
- Aset aplikasi
Data teks sederhana disimpan langsung di {i>clipboard<i}, sementara data kompleks disimpan sebagai referensi yang diselesaikan aplikasi penempelan dengan penyedia konten.
Fitur salin dan tempel berfungsi di dalam dan di antara aplikasi yang menerapkan kerangka kerja tersebut.
Karena sebagian framework menggunakan penyedia konten, dokumen ini mengasumsikan bahwa Anda memiliki pengetahuan dasar tentang Android Content Provider API.
Menggunakan teks
Beberapa komponen mendukung tindakan menyalin dan menempelkan teks secara langsung, seperti yang ditunjukkan pada pada tabel berikut.
Komponen | Menyalin teks | Menempelkan teks |
---|---|---|
DasarTeks Dasar | ✅ | ✅ |
Bidang Bidang | ✅ | ✅ |
Penampung Pilihan | ✅ |
Misalnya, Anda dapat menyalin teks di kartu ke papan klip
dalam cuplikan berikut dan menempelkan teks yang disalin ke TextField
.
Anda menampilkan menu untuk menempelkan teks dengan
menggeser & menahan TextField
, atau dengan mengetuk tuas kursor.
val textFieldState = rememberTextFieldState()
Column {
Card {
SelectionContainer {
Text("You can copy this text")
}
}
BasicTextField(state = textFieldState)
}
Anda dapat menempelkan teks dengan pintasan keyboard berikut: Ctrl+V . Pintasan keyboard juga tersedia secara default. Lihat Menangani tindakan keyboard untuk mengetahui detailnya.
Menyalin dengan ClipboardManager
Anda dapat menyalin teks ke papan klip dengan ClipboardManager
.
Metode setText() menyalin
objek String yang diteruskan ke papan klip.
Cuplikan berikut menyalin "Halo, papan klip"
ke papan klip saat pengguna mengklik tombol.
// 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")
}
Cuplikan berikut melakukan hal yang sama, tetapi memberi Anda kontrol yang lebih terperinci.
Kasus penggunaan yang umum adalah menyalin konten sensitif,
seperti sandi. ClipEntry
mendeskripsikan item di papan klip.
Objek ini berisi objek ClipData
yang mendeskripsikan data di papan klip.
Metode ClipData.newPlainText()
adalah metode praktis untuk
membuat objek ClipData
dari objek String.
Anda dapat menetapkan objek ClipEntry
yang dibuat ke papan klip
dengan memanggil metode setClip()
di atas objek 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")
}
Tempel dengan ClipboardManager
Anda dapat mengakses teks yang disalin ke papan klip
dengan memanggil metode getText()
di ClipboardManager
.
Metode getText()
menampilkan objek AnnotatedString
saat teks disalin di papan klip.
Cuplikan berikut menambahkan teks di papan klip
ke teks di 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")
}
}
Menggunakan konten lengkap
Pengguna menyukai gambar, video, dan konten ekspresif lainnya.
Aplikasi Anda dapat memungkinkan pengguna menyalin konten kaya dengan
ClipboardManager
dan ClipEntry
.
Pengubah contentReceiver
membantu Anda menerapkan konten lengkap yang ditempel.
Menyalin konten lengkap
Aplikasi Anda tidak dapat menyalin konten kaya langsung ke papan klip.
Sebagai gantinya, aplikasi Anda meneruskan objek URI
ke papan klip
dan memberikan akses ke konten dengan ContentProvider
.
Cuplikan kode berikut menunjukkan cara menyalin gambar JPEG ke papan klip.
Lihat Menyalin aliran data untuk mengetahui detailnya.
// 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")
}
Menempelkan konten lengkap
Dengan pengubah contentReceiver
, Anda dapat menangani menempelkan konten kaya
ke BasicTextField
di komponen yang diubah.
Cuplikan kode berikut menambahkan URI data gambar yang ditempelkan
ke daftar objek 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)
)
Pengubah contentReceiver
menggunakan objek ReceiveContentListener
sebagai argumennya dan memanggil metode onReceive
dari objek yang diteruskan saat pengguna menempelkan data
ke BasicTextField
di dalam komponen yang diubah.
Objek TransferableContent
diteruskan ke metode onReceive,
yang menjelaskan data yang dapat ditransfer antar-aplikasi
dengan menempelkannya dalam {i>casing<i} ini.
Anda dapat mengakses objek ClipEntry
dengan merujuk ke atribut clipEntry
.
Objek ClipEntry
dapat memiliki beberapa objek ClipData.Item
saat pengguna memilih beberapa gambar dan menyalinnya ke papan klip
ke titik akhir pelanggan.
Anda harus menandai objek ClipData.Item
yang digunakan atau diabaikan,
dan menampilkan TransferableContent
yang berisi
objek ClipData.Item
yang diabaikan
sehingga pengubah contentReceiver
ancestor terdekat dapat menerimanya.
Metode TransferableContent.hasMediaType()
dapat membantu Anda menentukan
apakah objek TransferableContent
dapat menyediakan item
dengan jenis media.
Misalnya, panggilan metode berikut menampilkan true
jika objek TransferableContent
dapat memberikan gambar.
transferableContent.hasMediaType(MediaType.Image)
Menangani data yang kompleks
Anda dapat menyalin data yang kompleks ke {i>clipboard<i} dengan cara yang sama seperti yang Anda lakukan untuk konten lengkap. Lihat Menggunakan penyedia konten untuk menyalin data kompleks untuk mengetahui detailnya.
Anda juga dapat menangani penempelan data kompleks
dengan cara yang sama untuk konten yang kaya.
Anda dapat menerima URI data yang ditempel.
Data sebenarnya dapat diambil dari ContentProvider
.
Lihat Mengambil data dari penyedia untuk mengetahui informasi selengkapnya.
Masukan untuk menyalin konten
Pengguna mengharapkan umpan balik saat mereka menyalin konten ke {i>clipboard<i}, jadi selain kerangka kerja yang mendukung {i>copy<i} dan {i>paste<i}, Android menampilkan UI default kepada pengguna saat mereka menyalin di Android 13 (API level 33) dan lebih tinggi. Karena fitur ini, ada risiko notifikasi duplikat. Anda dapat mempelajari kasus ekstrem ini lebih lanjut di Menghindari notifikasi duplikat.
Berikan masukan secara manual kepada pengguna saat menyalin di Android 12L (API level 32) dan yang lebih rendah. Lihat rekomendasi.
Konten sensitif
Jika Anda memilih untuk mengizinkan aplikasi menyalin konten sensitif ke papan klip, seperti sandi, aplikasi Anda harus memberi tahu sistem sehingga sistem dapat menghindari menampilkan konten sensitif yang disalin di UI (gambar 2).
Anda harus menambahkan tanda ke ClipDescription
di ClipData
sebelum memanggil metode setClip()
melalui objek 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)
}
}