O framework baseado na área de transferência do Android para copiar e colar oferece suporte a tipos de dados primitivos e complexos, incluindo:
- Strings de texto
- Estruturas de dados complexas
- Dados de texto e fluxo binário
- Recursos de aplicativos
Dados de texto simples são armazenados diretamente na área de transferência, enquanto dados complexos são armazenados como uma referência que o aplicativo de colagem resolve com um provedor de conteúdo.
A cópia e a colagem funcionam em um aplicativo e entre aplicativos que implementam o framework.
Como parte do framework usa provedores de conteúdo, este documento pressupõe certa familiaridade com a API Android Content Provider.
Trabalhar com texto
Alguns componentes oferecem suporte à cópia e colagem de texto, conforme mostrado na tabela a seguir.
| Componente | Copiando texto | Colando texto |
|---|---|---|
| BasicTextField | ✅ | ✅ |
| TextField | ✅ | ✅ |
| SelectionContainer | ✅ |
Por exemplo, você pode copiar o texto no card para a área de transferência no snippet a seguir e colar o texto copiado no TextField.
Mostre o menu para colar o texto tocando e mantendo pressionado o TextField ou tocando no marcador do cursor.
val textFieldState = rememberTextFieldState() Column { Card { SelectionContainer { Text("You can copy this text") } } BasicTextField(state = textFieldState) }
Você pode colar o texto com o seguinte atalho de teclado: Ctrl+V . O atalho de teclado também está disponível por padrão. Consulte Processar ações do teclado para mais detalhes.
Copiar com ClipboardManager
Você pode copiar textos para a área de transferência com ClipboardManager.
O método setText() copia
o objeto AnnotatedString transmitido para a área de transferência.
O snippet a seguir copia "Hello, clipboard" para a área de transferência quando o usuário clica no botão.
// Retrieve a ClipboardManager object val clipboardManager = LocalClipboardManager.current Button( onClick = { // Copy "Hello, clipboard" to the clipboard clipboardManager.setText(AnnotatedString("Hello, clipboard")) } ) { Text("Click to copy a text") }
O snippet a seguir faz a mesma coisa, mas oferece um controle mais granular.
Um caso de uso comum é a cópia de conteúdo sensível,
como senhas. ClipEntry descreve um item na área de transferência.
Ele contém um ClipData objeto que descreve os dados na área de transferência.
ClipData.newPlainText() método é um método de conveniência para
criar um objeto ClipData de um objeto String.
Você pode definir o objeto ClipEntry criado na área de transferência
chamando o método setClip()
no objeto 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") }
Colar com ClipboardManager
Você pode acessar o texto copiado para a área de transferência
chamando o getText() método
no ClipboardManager.
O método getText() retorna um objeto AnnotatedString quando um texto é copiado na área de transferência.
O snippet a seguir anexa o texto na área de transferência ao texto no TextField.
val 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(annotatedString.text) } } } ) { Text("Click to paste the text in the clipboard") } }
Trabalhar com conteúdo avançado
Os usuários adoram imagens, vídeos e outros conteúdos expressivos.
Seu app pode permitir que o usuário copie conteúdo avançado com ClipboardManager e ClipEntry.
O modificador contentReceiver ajuda a implementar a colagem de conteúdo avançado.
Copiar conteúdo avançado
Seu app não pode copiar conteúdo avançado diretamente para a área de transferência.
Em vez disso, seu app transmite um objeto URI para a área de transferência
e fornece acesso ao conteúdo com um ContentProvider.
O snippet de código a seguir mostra como copiar uma imagem JPEG para a área de transferência.
Consulte Copiar fluxos de dados para mais detalhes.
// 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") }
Colar um conteúdo avançado
Com o modificador contentReceiver, você pode processar a colagem de conteúdo avançado
em BasicTextField no componente modificado.
O snippet de código a seguir adiciona o URI colado de um dado de imagem
a uma lista de Uri objetos.
// A URI list of images val imageList = remember { mutableStateListOf<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) )
O modificador contentReceiver usa um objeto ReceiveContentListener
como argumento e chama o método onReceive
do objeto transmitido quando o usuário cola dados
no BasicTextField dentro do componente modificado.
Um objeto TransferableContent é transmitido para o método onReceive,
que descreve os dados que podem ser transferidos entre apps
colando nesse caso.
Você pode acessar o objeto ClipEntry consultando o atributo clipEntry.
Um ClipEntry objeto pode ter vários ClipData.Item objetos
quando o usuário seleciona várias imagens e as copia para a área de transferência
por exemplo.
Marque consumido ou ignorado para cada objeto ClipData.Item e retorne um TransferableContent contendo os objetos ClipData.Item ignorados para que o modificador contentReceiver ancestral mais próximo possa recebê-lo.
O método TransferableContent.hasMediaType() pode ajudar a determinar
se o objeto TransferableContent pode fornecer um item
com o tipo de mídia.
Por exemplo, a chamada de método a seguir retorna true se o objeto TransferableContent puder fornecer uma imagem.
transferableContent.hasMediaType(MediaType.Image)
Trabalhar com dados complexos
Você pode copiar dados complexos para a área de transferência da mesma maneira que faz para o conteúdo avançado. Consulte Usar provedores de conteúdo para copiar dados complexos para mais detalhes.
Você também pode processar as colagens de dados complexos da mesma maneira que para o conteúdo avançado.
Você pode receber um URI dos dados colados.
Os dados reais podem ser recuperados de um ContentProvider.
Consulte Recuperar dados do provedor para mais informações.
Feedback para copiar conteúdo
Os usuários esperam feedback ao copiar conteúdo para a área de transferência. Portanto, além do framework que permite copiar e colar, o Android mostra uma interface padrão quando usuários executam ações de cópia no Android 13 (nível da API 33) e versões mais recentes. Devido a esse recurso, há risco de notificação duplicada. Saiba mais sobre esse caso extremo em Evitar notificações duplicadas.
Envie feedback manualmente aos usuários que executam ações de cópia no Android 12L (nível 32 da API) e versões anteriores. Consulte a recomendação.
Conteúdo sensível
Se você escolher que seu app permita que o usuário copie conteúdo sensível para a área de transferência, como senhas, seu app precisa informar o sistema para que ele possa evitar mostrar o conteúdo sensível copiado na interface (Figura 2).
Adicione um marcador a ClipDescription em ClipData
antes de chamar o método setClip() no objeto 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) } }