ה-framework מבוסס-הלוח של Android להעתקה והדבקה תומכת בסוגי נתונים פרימיטיביים ומורכבים, כולל:
- מחרוזות טקסט
- מבני נתונים מורכבים
- נתוני מקורות טקסט ובינאריים
- נכסי אפליקציות
נתוני טקסט פשוטים מאוחסנים ישירות בלוח העריכה, ואילו נתונים מורכבים מאוחסנים כהפניה שאפליקציית ההדבקה פותרת עם ספק התוכן.
אפשר להעתיק ולהדביק גם בתוך אפליקציה וגם בין אפליקציות שמטמיעות את המסגרת.
מכיוון שחלק מהמסגרת משתמש בספקי תוכן, המסמך הזה מבוסס על ההנחה שיש לכם ידע בסיסי ב-Android Content Provider API.
עבודה עם טקסט
רכיבים מסוימים תומכים בהעתקה ובהדבקה של טקסט מחוץ לתיבה, כפי שמוצג ב- בטבלה הבאה.
רכיב | העתקת הטקסט מתבצעת | מתבצעת הדבקה של הטקסט |
---|---|---|
BasicTextField (שדה טקסט בסיסי) | ✅ | ✅ |
TextField | ✅ | ✅ |
SelectionContainer | ✅ |
לדוגמה, אפשר להעתיק את הטקסט שבכרטיס ללוח העריכה.
בקטע הקוד הבא ומדביקים את הטקסט שהועתק ברכיב TextField
.
כדי להציג את התפריט להדבקת הטקסט, לוחצים לחיצה ארוכה על TextField
או מקישים על ידית הסמן.
val textFieldState = rememberTextFieldState()
Column {
Card {
SelectionContainer {
Text("You can copy this text")
}
}
BasicTextField(state = textFieldState)
}
אפשר להדביק את הטקסט באמצעות מקשי הקיצור הבאים: Ctrl+V מקשי הקיצור זמינים גם כברירת מחדל. פרטים נוספים זמינים במאמר טיפול בפעולות במקלדת.
העתקה באמצעות ClipboardManager
אפשר להעתיק הודעות טקסט ללוח באמצעות ClipboardManager
.
שיטת setText() מועתקת
את אובייקט המחרוזת שהועבר ללוח.
קטע הקוד הבא מעתיק את הטקסט 'שלום, הלוח' ללוח כשהמשתמש לוחץ על הלחצן.
// 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")
}
קטע הקוד הבא עושה את אותו הדבר, אבל נותן לכם שליטה מפורטת יותר.
תרחיש לדוגמה נפוץ הוא העתקת תוכן רגיש.
כמו סיסמה. ClipEntry
מתאר פריט בלוח העריכה.
הוא מכיל אובייקט ClipData
שמתאר את הנתונים שבבורר.
השיטה ClipData.newPlainText()
היא שיטה נוחה ליצירת אובייקט ClipData
מאובייקט String.
אפשר להגדיר את אובייקט ClipEntry
שנוצר ללוח
באמצעות קריאה לשיטה setClip().
מעל לאובייקט 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")
}
הדבקה באמצעות ClipboardManager
אפשר לגשת לטקסט שהועתק ללוח
באמצעות קריאה ל-getText()
מעל ClipboardManager
.
השיטה getText()
מחזירה אובייקט AnnotatedString
כשטקסט מועתק ללוח.
קטע הקוד הבא מצרף טקסט ללוח
לטקסט שב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")
}
}
עבודה עם תוכן עשיר
משתמשים אוהבים תמונות, סרטונים ותוכן נוסף שמבטא את הרגשות שלהם.
האפליקציה שלכם יכולה לאפשר למשתמשים להעתיק תוכן עשיר באמצעות ClipboardManager
ו-ClipEntry
.
תכונת הצירוף contentReceiver
עוזרת להטמיע הדבקה של תוכן עשיר.
העתקת תוכן עשיר
האפליקציה שלך לא יכולה להעתיק תוכן עשיר ישירות ללוח.
במקום זאת, האפליקציה מעבירה אובייקט URI
ללוח העריכה
ומספק גישה לתוכן באמצעות ContentProvider
.
קטע הקוד הבא מראה איך להעתיק תמונת JPEG ללוח.
פרטים נוספים זמינים במאמר בנושא העתקת מקורות הנתונים.
// 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")
}
הדבקת תוכן עשיר
בעזרת המאפיין contentReceiver
אפשר להדביק תוכן עשיר ב-BasicTextField
ברכיב ששונה.
קטע הקוד הבא מוסיף את ה-URI של נתוני התמונה שהועתקו לרשימת אובייקטים מסוג 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)
)
המשתנה המשנה contentReceiver
מקבל אובייקט ReceiveContentListener
כארגומנטים שלו, ומפעיל את השיטה onReceive
של האובייקט שהוענק כשהמשתמש מדביק נתונים ב-BasicTextField
בתוך הרכיב ששונה.
אובייקט TransferableContent
מועבר ל-method onReceive, שמתאר את הנתונים שאפשר להעביר בין אפליקציות באמצעות הדבקה במקרה הזה.
אפשר לגשת לאובייקט ClipEntry
על ידי הפניה למאפיין clipEntry
.
אובייקט ClipEntry
יכול לכלול כמה אובייקטים מסוג ClipData.Item
, למשל כשהמשתמש בוחר כמה תמונות ומעתיק אותן ללוח.
צריך לסמן כל אובייקט ClipData.Item
כ'נוצר' או כ'מוזנח', ולהחזיר TransferableContent
שמכיל את אובייקטי ה-ClipData.Item
שהוזנחו, כדי שהמופך contentReceiver
של האב הקרוב ביותר יוכל לקבל אותו.
השיטה TransferableContent.hasMediaType()
יכולה לעזור לכם לקבוע אם אובייקט TransferableContent
יכול לספק פריט עם סוג המדיה.
לדוגמה, הפעלת ה-method הבאה מחזירה את הערך true
אם האובייקט TransferableContent
יכול לספק תמונה.
transferableContent.hasMediaType(MediaType.Image)
עבודה עם נתונים מורכבים
אפשר להעתיק נתונים מורכבים ללוח בדיוק כמו לגבי תוכן עשיר. פרטים נוספים זמינים במאמר שימוש בספקי תוכן להעתקת נתונים מורכבים.
אפשר גם לטפל בהדבקה של נתונים מורכבים
בדיוק כמו לגבי תוכן עשיר.
אפשר לקבל URI של הנתונים שהועתקו.
אפשר לאחזר את הנתונים בפועל מ-ContentProvider
.
מידע נוסף זמין במאמר אחזור נתונים מהספק.
משוב על העתקת תוכן
משתמשים מצפים לקבל משוב כשהם מעתיקים תוכן ללוח העריכה, ולכן בנוסף למסגרת שמפעילה את ההעתקה וההדבקה, ממשק המשתמש שמוגדר כברירת מחדל מוצג למשתמשים ב-Android 13 (API ברמה 33) ואילך כשהם מעתיקים. בגלל התכונה הזו, יש סיכון לקבל התראה כפולה. מידע נוסף על מקרה קיצון כזה זמין במאמר הימנעות מהצגת התראות כפולות.
שליחת משוב למשתמשים באופן ידני בזמן העתקה ב-Android 12L (רמת API 32) ומטה. כדאי לעיין בהמלצה.
תוכן רגיש
אם תבחרו לאפשר למשתמש להעתיק תוכן רגיש ללוח עבור האפליקציה, כמו סיסמאות, האפליקציה חייבת להודיע למערכת כדי שהמערכת תוכל להימנע מהצגת התוכן הרגיש שהועתק בממשק המשתמש (איור 2).
צריך להוסיף דגל ל-ClipDescription
ב-ClipData
לפני שמפעילים את השיטה setClip()
על האובייקט 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)
}
}