Le framework Android basé sur le presse-papiers pour la copie et le collage est compatible avec les types de données primitifs et complexes, y compris les suivants :
- Chaînes de texte
- Structures de données complexes
- Données de flux textuelles et binaires
- Composants Application
Les données de texte simples sont stockées directement dans le presse-papiers, tandis que les données complexes sont stockées comme référence que l'application de collage se résout avec un fournisseur de contenu.
Les opérations de copier-coller fonctionnent aussi bien au sein d'une application qu'entre les applications qui implémentent le framework.
Étant donné qu'une partie du framework utilise des fournisseurs de contenu, Dans ce document, nous partons du principe que vous connaissez l'API Content Provider pour Android.
Travailler avec du texte
Certains composants permettent de copier et de coller du texte directement, comme indiqué dans le tableau suivant.
Component | Copie du texte... | Collage du texte... |
---|---|---|
Champ de texte de base | ✅ | ✅ |
TextField | ✅ | ✅ |
SelectionContainer | ✅ |
Par exemple, vous pouvez copier le texte de la fiche dans le presse-papiers dans l'extrait de code suivant, puis coller le texte copié dans TextField
.
Pour afficher le menu permettant de coller le texte, appuyez de manière prolongée sur TextField
ou sur la poignée du curseur.
val textFieldState = rememberTextFieldState()
Column {
Card {
SelectionContainer {
Text("You can copy this text")
}
}
BasicTextField(state = textFieldState)
}
Vous pouvez coller le texte à l'aide du raccourci clavier suivant: Ctrl+V Le raccourci clavier est également disponible par défaut. Pour en savoir plus, consultez Gérer les actions du clavier.
Copier avec ClipboardManager
Vous pouvez copier du texte dans le presse-papiers avec ClipboardManager
.
Sa méthode setText() copie l'objet String transmis dans le presse-papiers.
L'extrait de code suivant copie "Hello, presse-papiers"
dans le presse-papiers lorsque
l'utilisateur clique sur le bouton.
// 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")
}
L'extrait de code suivant fait la même chose, mais vous offre un contrôle plus précis.
Un cas d'utilisation courant consiste à copier du contenu sensible,
comme le mot de passe. ClipEntry
décrit un élément du presse-papiers.
Il contient un objet ClipData
qui décrit les données du presse-papiers.
La méthode ClipData.newPlainText()
est une méthode pratique
créer un objet ClipData
à partir d'un objet String.
Vous pouvez ajouter l'objet ClipEntry
créé dans le presse-papiers
en appelant la méthode setClip() ;
sur l'objet 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")
}
Coller avec ClipboardManager
Vous pouvez accéder au texte copié dans le presse-papiers
en appelant la méthode getText()
pendant ClipboardManager
.
Sa méthode getText()
renvoie un objet AnnotatedString
.
Lorsqu'un texte est copié dans le presse-papiers.
L'extrait de code suivant ajoute du texte dans le presse-papiers
au texte de 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")
}
}
Utiliser du contenu enrichi
Les utilisateurs adorent les images, les vidéos et les autres contenus expressifs.
Votre application peut permettre à l'utilisateur de copier du contenu enrichi avec
ClipboardManager
et ClipEntry
.
Le modificateur contentReceiver
vous aide à implémenter le collage de contenu enrichi.
Copier du contenu enrichi
Votre application ne peut pas copier directement du contenu enrichi dans le presse-papiers.
À la place, votre application transmet un objet URI
au presse-papiers
et permet d'accéder au contenu à l'aide d'un ContentProvider
.
L'extrait de code suivant montre comment copier une image JPEG dans le presse-papiers.
Pour en savoir plus, consultez Copier des flux de données.
// 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")
}
Coller un contenu enrichi
Avec le modificateur contentReceiver
, vous pouvez gérer le collage de contenu enrichi dans BasicTextField
dans le composant modifié.
L'extrait de code suivant ajoute l'URI collé d'une donnée d'image
à une liste d'objets 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)
)
Le modificateur contentReceiver
accepte un objet ReceiveContentListener
.
comme argument et appelle onReceive
de l'objet transmis lorsque l'utilisateur colle des données
au BasicTextField
à l'intérieur du composant modifié.
Un objet TransferableContent
est transmis à la méthode onReceive, qui décrit les données pouvant être transférées entre les applications en les collant dans ce cas.
Vous pouvez accéder à l'objet ClipEntry
en vous référant à l'attribut clipEntry
.
Un objet ClipEntry
peut comporter plusieurs objets ClipData.Item
lorsque l'utilisateur sélectionne plusieurs images et les copie dans le presse-papiers, par exemple.
Vous devez marquer les objets comme consommés ou ignorés pour chaque objet ClipData.Item
.
et renvoyer une TransferableContent
contenant
les objets ClipData.Item
ignorés.
afin que le modificateur contentReceiver
de l'ancêtre le plus proche puisse le recevoir.
La méthode TransferableContent.hasMediaType()
peut vous aider à déterminer si l'objet TransferableContent
peut fournir un élément avec le type de contenu.
Par exemple, l'appel de méthode suivant renvoie true
si l'objet TransferableContent
peut fournir une image.
transferableContent.hasMediaType(MediaType.Image)
Travailler avec des données complexes
Vous pouvez copier des données complexes dans le presse-papiers de la même manière que pour le contenu enrichi. Pour en savoir plus, consultez Utiliser des fournisseurs de contenu pour copier des données complexes.
Vous pouvez aussi gérer le collage de données complexes
de la même manière pour le contenu enrichi.
Vous pouvez recevoir un URI des données collées.
Les données réelles peuvent être récupérées à partir d'un ContentProvider
.
Pour en savoir plus, consultez Récupérer des données auprès du fournisseur.
Commentaires sur la copie de contenu
Les utilisateurs s'attendent à recevoir des commentaires lorsqu'ils copient du contenu dans le presse-papiers. Par conséquent, en plus du framework qui alimente le copier-coller, Android affiche une UI par défaut aux utilisateurs lorsqu'ils effectuent une copie dans Android 13 (niveau d'API 33) ou version ultérieure. En raison de cette fonctionnalité, vous risquez de recevoir des notifications en double. Pour en savoir plus sur ce cas particulier, consultez Éviter les notifications en double.
Envoyer manuellement des commentaires aux utilisateurs lors de la copie sous Android 12L (niveau d'API 32) ou version antérieure. Consultez la recommandation.
Contenu sensible
Si vous choisissez de permettre à l'utilisateur de copier du contenu sensible dans le presse-papiers, comme des mots de passe, votre application doit en informer le système afin qu'il évite d'afficher le contenu sensible copié dans l'UI (figure 2).
Vous devez ajouter un indicateur à ClipDescription
dans ClipData
avant d'appeler la méthode setClip()
sur l'objet 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)
}
}