Platforma do kopiowania i wklejania danych na podstawie schowka Androida obsługuje proste i złożone typy danych, w tym:
- Teksty
- Złożone struktury danych
- Dane strumieniowe tekstowe i binarne
- Komponenty z linkiem do aplikacji
Proste dane tekstowe są przechowywane bezpośrednio w schowku, a dane złożone są przechowywane jako odwołanie, które aplikacja do wklejania rozwiązuje za pomocą dostawcy treści.
Kopiowanie i wklejanie działa zarówno w aplikacji, jak i między aplikacjami którzy biorą udział w programie.
Ponieważ w ramach naszego systemu korzystamy z usług dostawców treści, zakładamy, że zna on interfejs API dostawcy treści na Androida.
Praca z tekstem
Niektóre komponenty obsługują kopiowanie i wklejanie tekstu, jak pokazano w tabeli poniżej.
Komponent | Kopiuję tekst | Wklejanie tekstu |
---|---|---|
BasicTextField | ✅ | ✅ |
Pole tekstowe | ✅ | ✅ |
Kontener wyboru | ✅ |
Możesz na przykład skopiować tekst z karty do schowka w tym fragmencie kodu i wklejć go do pola TextField
.
W menu możesz wkleić tekst przez
dotknij & przytrzymaj TextField
lub dotknij uchwytu kursora.
val textFieldState = rememberTextFieldState()
Column {
Card {
SelectionContainer {
Text("You can copy this text")
}
}
BasicTextField(state = textFieldState)
}
Możesz wkleić tekst, korzystając z tego skrótu klawiszowego: Ctrl+V . Dostępny jest też domyślnie skrót klawiszowy. Więcej informacji znajdziesz w artykule Obsługa działań klawiatury.
Kopiuj z ClipboardManager
Możesz skopiować tekst do schowka za pomocą ClipboardManager
.
Metoda setText() kopiuje przekazany obiekt String do schowka.
Ten fragment to „Cześć, schowek”
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("Hello, clipboard")
}
) {
Text("Click to copy a text")
}
Poniższy fragment kodu działa tak samo, ale daje Ci większą kontrolę.
Typowym przypadkiem użycia jest kopiowanie treści poufnych, takich jak hasło. ClipEntry
opisuje element na schowku.
Zawiera obiekt ClipData
opisujący dane w schowku.
ClipData.newPlainText()
to wygodna metoda do tworzenia obiektu ClipData
na podstawie obiektu String.
Możesz umieścić utworzony obiekt ClipEntry
w schowku
przez wywołanie metody setClip()
nad obiektem 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ą narzędzia ClipboardManager
Możesz uzyskać dostęp do tekstu skopiowanego do schowka
wywołując metodę getText()
w okresie ClipboardManager
.
Jego metoda getText()
zwraca obiekt AnnotatedString
gdy tekst jest kopiowany do schowka.
Ten fragment dołącza tekst w schowku
do tekstu w tabeli 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")
}
}
Praca z treściami szczegółowymi
Użytkownicy uwielbiają zdjęcia, filmy i inne treści ekspresyjne.
Aplikacja może umożliwiać użytkownikowi kopiowanie treści multimedialnych za pomocą funkcji ClipboardManager
i ClipEntry
.
Modyfikator contentReceiver
ułatwia wklejanie treści sformatowanych.
Kopiowanie szczegółowych treści
Aplikacja nie może kopiować szczegółowych treści bezpośrednio do schowka.
Zamiast tego aplikacja przekazuje obiekt URI
do schowka
i zapewnia dostęp do treści za pomocą komponentu ContentProvider
.
Ten fragment kodu pokazuje, jak skopiować obraz JPEG do schowka.
Więcej informacji znajdziesz w artykule 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")
}
Wklejanie szczegółowych treści
Dzięki modyfikatorowi contentReceiver
możesz wklejać treści sformatowane
do BasicTextField
w zmodyfikowanym komponencie.
Następujący fragment kodu dodaje wklejony identyfikator URI danych obrazu
do listy obiektów 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)
)
Modyfikator contentReceiver
przyjmuje obiekt ReceiveContentListener
jako argument i wywołuje funkcję onReceive
metody przekazywanego 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 wklejanie.
Dostęp do obiektu ClipEntry
możesz uzyskać, korzystając z atrybutu clipEntry
.
Obiekt ClipEntry
może zawierać wiele obiektów ClipData.Item
, gdy użytkownik wybierze kilka obrazów i skopiuje je do schowka.
Należy oznaczyć jako wykorzystane lub zignorowane dla każdego obiektu ClipData.Item
,
i zwrócą TransferableContent
zawierający
ignorowane obiekty ClipData.Item
aby mógł ją odebrać najbliższy modyfikator nadrzędny contentReceiver
.
Metoda TransferableContent.hasMediaType()
może pomóc Ci określić, czy obiekt TransferableContent
może dostarczyć element z typem nośnika.
Na przykład wywołanie metody zwraca true
, jeśli obiekt TransferableContent
może dostarczyć obraz.
transferableContent.hasMediaType(MediaType.Image)
Praca ze złożonymi danymi
Możesz kopiować złożone dane do schowka w taki sam sposób jak w przypadku treści osadzonych. Więcej informacji znajdziesz w artykule Kopiowanie złożonych danych za pomocą dostawców treści.
W taki sam sposób możesz też wklejać złożone dane w przypadku treści osadzonych.
Możesz otrzymać identyfikator URI wklejonych danych.
Prawdziwe dane można pobrać z ContentProvider
.
Więcej informacji znajdziesz w artykule Pobieranie danych od dostawcy.
Opinie na temat kopiowania treści
Użytkownicy oczekują informacji po skopiowaniu treści do schowka, więc oprócz platformy, na której opiera się kopiowanie i wklejanie, Android wyświetla użytkownikom domyślny interfejs podczas kopiowania w Androidzie 13 (poziom API 33) i wyższe. Dzięki tej funkcji istnieje ryzyko zduplikowania powiadomienia. Więcej informacji o tym szczególnym przypadku znajdziesz w artykule Unikanie zduplikowanych powiadomień.
Ręczne przekazywanie opinii użytkownikom podczas kopiowania w Androidzie 12L (poziom API 32) i starszym. Zobacz rekomendację.
Treści drażliwe
Jeśli chcesz, aby aplikacja umożliwiała użytkownikowi kopiowanie treści poufnych, takich jak hasła, do schowka, musisz poinformować o tym system, aby nie wyświetlał skopiowanych treści poufnych w interfejsie użytkownika (rysunek 2).
Musisz dodać flagę do: ClipDescription
w: ClipData
przed wywołaniem metody setClip()
za pomocą obiektu 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)
}
}