Kopyala ve yapıştır

Kopyalama ve yapıştırma için Android'in panosuna dayalı çerçevesi aşağıdakiler dahil olmak üzere basit ve karmaşık veri türlerini destekler:

  • Metin dizeleri
  • Karmaşık veri yapıları
  • Metin ve ikili akış verileri
  • Uygulama öğeleri

Basit metin verileri doğrudan panoda saklanır. karmaşık veriler referans olarak depolanırken, bir içerik sağlayıcı ile çözüldüğünden emin olun.

Kopyalama ve yapıştırma, hem bir uygulama içinde hem de çerçeveyi uygulayan uygulamalar arasında çalışır.

Çerçevenin bir parçasında içerik sağlayıcılar kullanıldığı için bu belgede Android Content Provider API'si ile ilgili bilgi sahibi olunması varsayılmaktadır.

Metinle çalışma

Aşağıdaki gibi bazı bileşenler, metnin kutudan çıkarılarak kopyalanıp yapıştırılmasını destekler. aşağıdaki tabloda bulabilirsiniz.

Bileşen Metin kopyalama Metin yapıştırılıyor
Temel MetinAlanı
TextField
SelectionContainer

Örneğin, aşağıdaki snippet'te karttaki metni panoya kopyalayıp kopyalanan metni TextField alanına yapıştırabilirsiniz. Metni bir dokun ve TextField tuşunu basılı tutun veya imlecin tutamacına dokunun.

val textFieldState = rememberTextFieldState()

Column {
    Card {
        SelectionContainer {
            Text("You can copy this text")
        }
    }
    BasicTextField(state = textFieldState)
}

Metni şu klavye kısayoluyla yapıştırabilirsiniz: Ctrl+V . Klavye kısayolu da varsayılan olarak kullanılabilir. Ayrıntılar için Klavye işlemlerini işleme başlıklı makaleyi inceleyin.

ClipboardManager ile kopyala

ClipboardManager simgesini kullanarak metinleri panoya kopyalayabilirsiniz. setText() yöntemi, iletilen dize nesnesini panoya kopyalar. Aşağıdaki snippet "Merhaba, pano"yu kopyalar panoya gönderir.

// 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")
}

Aşağıdaki snippet aynı şeyi yapar, ancak size daha ayrıntılı kontrol sağlar. Yaygın kullanım alanlarından biri hassas içeriği kopyalamaktır, sağlayabilir. ClipEntry, panodaki bir öğeyi açıklar. Panodaki verileri açıklayan bir ClipData nesnesi içerir. ClipData.newPlainText() yöntemi, Dize nesnesinden bir ClipData nesnesi oluşturun. Oluşturulan ClipEntry nesnesini panoya ayarlayabilirsiniz setClip() yöntemini çağırarak ClipboardManager nesnesinin üzerinde görünür.

// 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")
}

ClipboardManager ile yapıştır

Panoya kopyalanan metne erişebilirsiniz getText() yöntemini çağırarak ClipboardManager üzerinden. getText() yöntemi, panoya metin kopyalandığında bir AnnotatedString nesnesi döndürür. Aşağıdaki snippet, panoya kopyalanan metni TextField içindeki metne ekler.

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")
    }
}

Zengin içeriklerle çalışma

Kullanıcılar resimleri, videoları ve diğer etkileyici içerikleri sever. Uygulamanız, kullanıcının ClipboardManager ve ClipEntry. contentReceiver değiştirici, zengin içeriği yapıştırmayı uygulamanıza yardımcı olur.

Zengin içeriği kopyalama

Uygulamanız, zengin içeriği doğrudan panoya kopyalayamıyor. Bunun yerine, uygulamanız panoya bir URI nesnesi iletir ve içeriğe bir ContentProvider ile erişim sağlar. Aşağıdaki kod snippet'inde, bir JPEG resminin panoya nasıl kopyalanacağı gösterilmektedir. Ayrıntılar için Veri akışlarını kopyalama başlıklı makaleyi inceleyin.

// 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")
}

Zengin içerik yapıştırma

contentReceiver değiştiricisiyle zengin içerikleri yapıştırabilirsiniz. değişiklik yapılan bileşende BasicTextField olarak değişir. Aşağıdaki kod snippet'i, bir resim verisinin yapıştırılan URI'sini Uri nesnelerinin listesine ekler.

// 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)
)

contentReceiver değiştiricisi ReceiveContentListener nesne alır (onReceive bağımsız değişkeni) çağırarak kullanıcı verileri yapıştırdığında iletilen nesnenin yöntemi ifadesini BasicTextField içine koyabilirsiniz.

onReceive yöntemine bir TransferableContent nesnesi iletilir. Bu nesne, bu durumda yapıştırılarak uygulamalar arasında aktarılabilen verileri tanımlar. clipEntry özelliğine başvurarak ClipEntry nesnesine erişebilirsiniz.

Örneğin, kullanıcı birkaç resim seçip bunları panosuna kopyaladığında bir ClipEntry nesnesinde birden fazla ClipData.Item nesnesi olabilir. Her ClipData.Item nesnesi için tüketildi veya yoksayıldı olarak işaretlemeli ve en yakın ata contentReceiver değiştiricinin alabilmesi için yoksayılan ClipData.Item nesnelerini içeren bir TransferableContent döndürmelisiniz.

TransferableContent.hasMediaType() yöntemi, kitlenizin TransferableContent nesnesinin bir öğe sağlayıp sağlayamayacağı girin. Örneğin, aşağıdaki yöntem çağrısı true değerini döndürür TransferableContent nesnesi resim sağlayabiliyorsa.

transferableContent.hasMediaType(MediaType.Image)

Karmaşık verilerle çalışma

Karmaşık verileri, zengin içerik için yaptığınız gibi panoya kopyalayabilirsiniz. Ayrıntılar için Karmaşık verileri kopyalamak için içerik sağlayıcıları kullanma bölümüne bakın.

Karmaşık verilerin yapıştırma işlemlerini de zengin içerik için aynı şekilde yapabilirsiniz. Yapıştırılan verilerin URI'sini alabilirsiniz. Gerçek veriler ContentProvider dosyasından alınabilir. Daha fazla bilgi için Sağlayıcıdan veri alma başlıklı makaleye bakın.

İçerik kopyalama hakkında geri bildirim

Kullanıcılar, içeriği panoya kopyalarken geri bildirim bekler. kopyalama ve yapıştırmayı destekleyen çerçevenin yanı sıra Android, kullanıcılar Android 13'te (API düzeyi 33) kopyalama yaparken kullanıcılara varsayılan bir kullanıcı arayüzü gösterir ve daha yüksek olabilir. Bu özellik nedeniyle yinelenen bildirim alma riski vardır. Bu uç destek durumu hakkında daha fazla bilgi edinmek için Yinelenen bildirimlerden kaçınma başlıklı makaleyi inceleyebilirsiniz.

Android 13 panosu bildirimini gösteren animasyon
Şekil 1. Android 13 ve sonraki sürümlerde içeriğin panosuna eklenmesiyle gösterilen kullanıcı arayüzü.

Android 12L (API düzeyi 32) ve önceki sürümlerde kopyalama işlemi sırasında kullanıcılara manuel olarak geri bildirim sağlayın. Öneriye göz atın.

Hassas içerik

Uygulamanızın, kullanıcının hassas içeriği panoya kopyalamasına izin vermeyi seçerseniz kullanıyorsanız uygulamanız, bunları sisteme Böylece sistem, kopyalanan hassas içeriği görüntülemekten kaçınabilir. arasındaki herhangi bir konumu bulmalıdır (şekil 2).

Hassas içeriği işaretleyen metin önizlemesi kopyalandı.
Şekil 2. Hassas içerik işaretiyle metin önizlemesi kopyalandı.

ClipData bölgesinde ClipDescription öğesine bir işaret eklemeniz gerekiyor ClipboardManager nesnesi üzerinden setClip() yöntemini çağırmadan önce:

// 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)
    }
}