چارچوب مبتنی بر بریدهدان 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() آن، شیء AnnotatedString ارسالشده را در بریدهدان کپی میکند.
قطعه کد زیر «سلام، بریدهدان» را
وقتی کاربر روی دکمه کلیک میکند در بریدهدان کپی میکند.
// 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") }
قطعه کد زیر همان کار را انجام میدهد، اما کنترل دقیقتری به شما میدهد.
یک مورد استفاده رایج کپی کردن محتوای حساس،
مانند گذرواژه است. ClipEntry موردی را در بریدهدان توصیف میکند.
این رویداد حاوی شیء ClipData است که دادههای موجود در بریدهدان را توصیف میکند.
روش ClipData.newPlainText() روشی راحت برای ایجاد شیء ClipData از شیء «رشته» است.
میتوانید شیء 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 اضافه میکند.
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") } }
کار با محتوای غنی
کاربران تصاویر، ویدیوها، و دیگر محتواهای گویا را دوست دارند.
برنامه شما میتواند به کاربر امکان دهد محتوای غنی را با
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 = 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) )
اصلاحکننده contentReceiver یک شیء ReceiveContentListener را بهعنوان آرگومان خود میگیرد و وقتی کاربر دادهها را در BasicTextField داخل مؤلفه اصلاحشده جایگذاری میکند، روش onReceive شیء ارسالشده را فراخوانی میکند.
یک شیء TransferableContent به روش onReceive ارسال میشود،
که دادههایی را که میتوانند بین برنامهها منتقل شوند
با جایگذاری در این مورد توصیف میکند.
با ارجاع به مشخصه clipEntry میتوانید به شیء ClipEntry دسترسی پیدا کنید.
یک شیء ClipEntry میتواند چندین شیء ClipData.Item داشته باشد
مثلاً وقتی کاربر چندین تصویر را انتخاب میکند و آنها را در بریدهدان کپی میکند.
باید برای هر شیء ClipData.Item، مصرفشده یا نادیدهگرفتهشده را علامتگذاری کنید،
و یک TransferableContent حاوی
اشیاء ClipData.Item نادیدهگرفتهشده را برگردانید
تا نزدیکترین اصلاحکننده contentReceiver بتواند آن را دریافت کند.
روش TransferableContent.hasMediaType() میتواند به شما کمک کند تعیین کنید
آیا شیء TransferableContent میتواند موردی با نوع رسانه ارائه دهد یا نه.
برای مثال، فراخوانی روش زیر true را برمیگرداند
اگر شیء TransferableContent بتواند تصویری ارائه دهد.
transferableContent.hasMediaType(MediaType.Image)
کار کردن با دادههای پیچیده
میتوانید دادههای پیچیده را به همان روشی که برای محتوای غنی انجام میدهید، در بریدهدان کپی کنید. برای جزئیات بیشتر، به استفاده از ارائهدهندگان محتوا برای کپی کردن دادههای پیچیده مراجعه کنید.
همچنین میتوانید جایگذاری دادههای پیچیده را
به همان روش برای محتوای غنی مدیریت کنید.
میتوانید شناسه منبع یکسان دادههای جایگذاریشده را دریافت کنید.
دادههای واقعی را میتوان از ContentProvider بازیابی کرد.
برای اطلاعات بیشتر، به بازیابی دادهها از ارائهدهنده مراجعه کنید.
بازخورد درباره کپی کردن محتوا
کاربران انتظار دارند وقتی محتوایی را در بریدهدان کپی میکنند بازخورد دریافت کنند، بنابراین علاوهبر چارچوبی که کپی و جایگذاری را تقویت میکند، Android در Android 13 (میانای برنامهسازی کاربردی سطح ۳۳) و بالاتر هنگام کپی کردن محتوا، میانای کاربری پیشفرضی به کاربران نشان میدهد. بهدلیل این ویژگی، خطر اعلان تکراری وجود دارد. میتوانید درباره این مورد خاص در جلوگیری از اعلانهای تکراری بیشتر بدانید.
هنگام کپی کردن در Android 12L (سطح API ۳۲) و پایینتر، بازخورد را بهصورت دستی به کاربران ارائه دهید. توصیه را ببینید.
محتوای حساس
اگر انتخاب کنید که برنامهتان به کاربر اجازه دهد محتوای حساس را در بریدهدان کپی کند، مثلاً گذرواژهها، برنامهتان باید به سیستم اطلاع دهد تا سیستم بتواند از نمایش محتوای حساس کپیشده در میانای کاربر جلوگیری کند (شکل ۲).
باید پرچمی به 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) } }