Oparta na schowku platforma Androida do kopiowania i wklejania obsługuje proste i złożone typy danych, w tym:
- Ciągi tekstowe
- Złożone struktury danych
- Dane tekstowe i strumieniowe dane binarne
- Zasoby aplikacji
Proste dane tekstowe są przechowywane bezpośrednio w schowku, natomiast dane złożone są przechowywane jako odwołanie, które aplikacja wklejająca rozwiązuje za pomocą mechanizmu dostarczania treści.
Kopiowanie i wklejanie działa zarówno w obrębie aplikacji, jak i między aplikacjami, które implementują platformę.
Część platformy korzysta z mechanizmów dostarczania treści, dlatego w tym dokumencie zakładamy, że masz pewną wiedzę na temat interfejsu Android Content Provider API.
Praca z tekstem
Niektóre komponenty obsługują kopiowanie i wklejanie tekstu od razu, jak pokazano w poniższej tabeli.
| Komponent | Kopiowanie tekstu | Wklejanie tekstu |
|---|---|---|
| BasicTextField | ✅ | ✅ |
| TextField | ✅ | ✅ |
| SelectionContainer | ✅ |
Możesz na przykład skopiować tekst z karty do schowka w tym fragmencie kodu i wkleić go do TextField.
Aby wyświetlić menu i wkleić tekst, naciśnij i przytrzymaj TextField lub kliknij uchwyt kursora.
val textFieldState = rememberTextFieldState() Column { Card { SelectionContainer { Text("You can copy this text") } } BasicTextField(state = textFieldState) }
Możesz wkleić tekst za pomocą skrótu klawiszowego Ctrl+V . Skrót klawiszowy jest też domyślnie dostępny. Szczegółowe informacje znajdziesz w sekcji Obsługa działań klawiatury.
Kopiuj za pomocą ClipboardManager
Możesz kopiować teksty do schowka za pomocą skrótu ClipboardManager.
Jego metoda setText() kopiuje przekazany obiekt AnnotatedString do schowka.
Poniższy fragment kodu kopiuje tekst „Hello, clipboard” do schowka, gdy użytkownik kliknie przycisk.
// 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") }
Poniższy fragment kodu robi to samo, ale zapewnia bardziej szczegółową kontrolę.
Typowym przypadkiem użycia jest kopiowanie treści poufnych, takich jak hasło. ClipEntry opisuje element w schowku.
Zawiera obiekt ClipData, który opisuje dane w schowku.
Metoda ClipData.newPlainText() to wygodna metoda tworzenia obiektu ClipData z obiektu String.
Utworzony obiekt ClipEntry możesz ustawić w schowku, wywołując metodę setClip() na obiekcie 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") }
Wklej za pomocą ClipboardManager
Dostęp do tekstu skopiowanego do schowka możesz uzyskać, wywołując metodę getText() w ClipboardManager.
Jego metoda getText() zwraca obiekt AnnotatedString, gdy tekst jest kopiowany do schowka.
Ten fragment kodu dołącza tekst ze schowka do tekstu w 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") } }
Praca ze szczegółowymi treściami
Użytkownicy uwielbiają obrazy, filmy i inne treści, które pozwalają im wyrazić siebie.
Aplikacja może umożliwiać użytkownikowi kopiowanie szczegółowych treści za pomocą funkcji ClipboardManager i ClipEntry.
Modyfikator contentReceiver pomaga we wdrażaniu wklejania szczegółowych treści.
Kopiowanie szczegółowych treści
Aplikacja nie może kopiować szczegółowych treści bezpośrednio do schowka.
Zamiast tego aplikacja przekazuje do schowka obiekt URI i zapewnia dostęp do treści za pomocą ContentProvider.
Poniższy fragment kodu pokazuje, jak skopiować obraz JPEG do schowka.
Szczegółowe informacje znajdziesz w sekcji Kopiowanie strumieni danych.
// 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") }
Wklej szczegółowe treści
Za pomocą modyfikatora contentReceiver możesz obsługiwać wklejanie szczegółowych treści do BasicTextField w zmodyfikowanym komponencie.
Poniższy fragment kodu dodaje wklejony identyfikator URI danych obrazu do listy obiektów Uri.
// 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) )
Modyfikator contentReceiver przyjmuje obiekt ReceiveContentListener jako argument i wywołuje metodę onReceive przekazanego obiektu, gdy użytkownik wkleja dane do BasicTextField w zmodyfikowanym komponencie.
Do metody onReceive przekazywany jest obiekt TransferableContent, który opisuje dane, które można przenosić między aplikacjami, w tym przypadku przez wklejenie.
Dostęp do obiektu ClipEntry możesz uzyskać, odwołując się do atrybutu clipEntry.
Obiekt ClipEntry może mieć kilka obiektów ClipData.Item, na przykład gdy użytkownik wybierze kilka obrazów i skopiuje je do schowka.
Każdy obiekt ClipData.Item należy oznaczyć jako wykorzystany lub zignorowany i zwrócić obiekt TransferableContent zawierający zignorowane obiekty ClipData.Item, aby najbliższy modyfikator nadrzędny contentReceiver mógł go otrzymać.
Metoda TransferableContent.hasMediaType() może pomóc Ci określić, czy obiekt TransferableContent może dostarczyć element z typem multimediów.
Na przykład to wywołanie metody zwraca true, jeśli obiekt TransferableContent może dostarczyć obraz.
transferableContent.hasMediaType(MediaType.Image)
Praca ze złożonymi danymi
Złożone dane możesz kopiować do schowka w taki sam sposób jak szczegółowe treści. Szczegółowe informacje znajdziesz w artykule Kopiowanie złożonych danych za pomocą mechanizmów dostarczania treści.
W ten sam sposób możesz też obsługiwać wklejanie złożonych danych w przypadku szczegółowych treści.
Możesz otrzymać identyfikator URI wklejonych danych.
Rzeczywiste dane można pobrać z ContentProvider.
Więcej informacji znajdziesz w artykule Pobieranie danych od dostawcy.
Opinie o kopiowaniu treści
Użytkownicy oczekują informacji zwrotnej, gdy kopiują treści do schowka, więc oprócz platformy, która obsługuje kopiowanie i wklejanie, Android wyświetla domyślny interfejs, gdy użytkownicy kopiują treści w Androidzie 13 (API na poziomie 33) lub nowszym. Z powodu tej funkcji istnieje ryzyko, że powiadomienie zostanie wysłane dwukrotnie. Więcej informacji o tym przypadku znajdziesz w sekcji Unikanie powiadomień o duplikatach.
Ręcznie przekazuj użytkownikom informacje zwrotne podczas kopiowania w Androidzie 12L (poziom interfejsu API 32) i starszych wersjach. Zobacz rekomendację.
Treści o charakterze kontrowersyjnym
Jeśli zdecydujesz, że aplikacja ma umożliwiać użytkownikowi kopiowanie do schowka treści poufnych, takich jak hasła, aplikacja musi poinformować o tym system, aby nie wyświetlał on skopiowanych treści poufnych w interfejsie (rysunek 2).
Przed wywołaniem metody setClip() w obiekcie ClipboardManager musisz dodać flagę do ClipDescription w ClipData:
// 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) } }