بخشهای بعدی چند مفهوم کلیدی برای فرآیند کشیدن و رها کردن را توضیح میدهند.
فرآیند کشیدن و رها کردن
چهار مرحله یا حالت در فرآیند کشیدن و رها کردن وجود دارد: شروع شده، ادامه دار، رها شده و پایان یافته.
- شروع شده
در پاسخ به حرکت کشیدن کاربر، برنامه شما تابع
startDragAndDrop()را فراخوانی میکند تا به سیستم بگوید که عملیات کشیدن و رها کردن را شروع کند. آرگومانهای این متد موارد زیر را ارائه میدهند:- دادههایی که باید کشیده شوند.
- فراخوانی برای ترسیم سایه درگ
- فرادادهای که دادههای کشیدهشده را توصیف میکند
- سیستم با فراخوانی برنامه شما برای دریافت سایه کشیدن پاسخ میدهد. سپس سیستم سایه کشیدن را روی دستگاه نمایش میدهد.
- در مرحله بعد، سیستم یک رویداد کشیدن با نوع اکشن
ACTION_DRAG_STARTEDرا به شنونده رویداد کشیدن همه اشیاءViewدر طرح فعلی ارسال میکند. برای ادامه دریافت رویدادهای کشیدن - از جمله یک رویداد رها کردن احتمالی - شنونده رویداد کشیدن بایدtrueبرگرداند. این باعث میشود شنونده در سیستم ثبت شود. فقط شنوندههای ثبت شده همچنان رویدادهای کشیدن را دریافت میکنند. در این مرحله، شنوندهها میتوانند ظاهر شیءViewهدف رها کردن خود را نیز تغییر دهند تا نشان دهند که View میتواند یک رویداد رها کردن را بپذیرد. - اگر شنوندهی رویداد کشیدن
falseرا برگرداند، رویدادهای کشیدن را برای عملیات فعلی دریافت نمیکند تا زمانی که سیستم یک رویداد کشیدن با نوع اکشنACTION_DRAG_ENDEDارسال کند. با برگرداندنfalse، شنونده به سیستم میگوید که علاقهای به عملیات کشیدن و رها کردن ندارد و نمیخواهد دادههای کشیده شده را بپذیرد.
- ادامه دارد
- کاربر به کشیدن ادامه میدهد. همزمان با اینکه سایه کشیدن، کادر اطراف یک هدف رها کردن را قطع میکند، سیستم یک یا چند رویداد کشیدن را به شنونده رویداد کشیدن هدف ارسال میکند. شنونده ممکن است ظاهر
Viewهدف رها کردن را در پاسخ به این رویداد تغییر دهد. به عنوان مثال، اگر رویداد نشان دهد که سایه کشیدن وارد کادر اطراف هدف رها کردن میشود - نوع عملACTION_DRAG_ENTERED- شنونده میتواند با برجسته کردنViewواکنش نشان دهد. - رها شده
- کاربر سایه کشیدن را درون کادر محدوده یک هدف رها کردن رها میکند. سیستم یک رویداد کشیدن با نوع اکشن
ACTION_DROPبه شنونده هدف رها کردن ارسال میکند. شیء رویداد کشیدن شامل دادههایی است که در فراخوانیstartDragAndDrop()که عملیات را آغاز میکند، به سیستم منتقل میشود. انتظار میرود شنونده در صورت پردازش موفقیتآمیز دادههای رها شده، مقدار بولیtrueبه سیستم برگرداند. : این مرحله فقط در صورتی رخ میدهد که کاربر سایه کشیدن را درون کادر محدوده یکViewکه شنونده آن برای دریافت رویدادهای کشیدن (یک هدف رها کردن) ثبت شده است، رها کند. اگر کاربر سایه کشیدن را در هر موقعیت دیگری رها کند، هیچ رویداد کشیدنACTION_DROPارسال نمیشود. - پایان یافت
بعد از اینکه کاربر سایه کشیدن را رها کرد، و بعد از اینکه سیستم ارسال کرد
یک رویداد کشیدن با نوع عمل
ACTION_DROPارسال کند، در صورت لزوم، سیستم یک رویداد کشیدن با نوع عملACTION_DRAG_ENDEDارسال میکند تا نشان دهد که عملیات کشیدن و رها کردن پایان یافته است. این کار صرف نظر از جایی که کاربر سایه کشیدن را رها میکند، انجام میشود. این رویداد به هر شنوندهای که برای دریافت رویدادهای کشیدن ثبت شده است، ارسال میشود، حتی اگر شنونده رویدادACTION_DROPرا نیز دریافت کند.
هر یک از این مراحل با جزئیات بیشتر در بخشی با عنوان «عملیات کشیدن و رها کردن» شرح داده شده است.
رویدادهای کشیدن
سیستم یک رویداد کشیدن (drag) را به شکل یک شیء DragEvent ارسال میکند که شامل یک نوع اکشن است که آنچه را که در فرآیند کشیدن و رها کردن اتفاق میافتد، توصیف میکند. بسته به نوع اکشن، شیء میتواند حاوی دادههای دیگری نیز باشد.
شنوندههای رویداد Drag، شیء DragEvent را دریافت میکنند. برای دریافت نوع عمل، شنوندهها DragEvent.getAction() را فراخوانی میکنند. شش مقدار ممکن وجود دارد که توسط ثابتهای کلاس DragEvent تعریف شدهاند و در جدول 1 توضیح داده شدهاند:
جدول 1. انواع اکشن DragEvent
| نوع اقدام | معنی |
|---|---|
ACTION_DRAG_STARTED | برنامه تابع startDragAndDrop() را فراخوانی میکند و یک سایهی درگ دریافت میکند. اگر شنونده بخواهد به دریافت رویدادهای درگ برای این عملیات ادامه دهد، باید مقدار boolean true به سیستم برگرداند. |
ACTION_DRAG_ENTERED | سایه کشیدن وارد کادر محدوده View شنونده رویداد کشیدن میشود. این اولین نوع اقدام رویدادی است که شنونده هنگام ورود سایه کشیدن به کادر محدوده دریافت میکند. |
ACTION_DRAG_LOCATION | پس از رویداد ACTION_DRAG_ENTERED ، سایهی کشیدن هنوز درون کادر محدودهی View مربوط به شنوندهی رویداد کشیدن قرار دارد. |
ACTION_DRAG_EXITED | پس از یک رویداد ACTION_DRAG_ENTERED و حداقل یک رویداد ACTION_DRAG_LOCATION ، سایهی درگ به خارج از کادر محدودهی View مربوط به شنوندهی رویداد درگ حرکت میکند. |
ACTION_DROP | سایه کشیدن (drag shadow) روی View مربوط به شنونده رویداد drag آزاد میشود. این نوع اکشن فقط در صورتی به شنونده شیء View ارسال میشود که شنونده در پاسخ به رویداد drag مربوط ACTION_DRAG_STARTED مقدار boolean true را برگرداند. این نوع اکشن در صورتی ارسال نمیشود که کاربر سایه کشیدن را روی View ای که شنونده آن ثبت نشده است رها کند یا اگر کاربر سایه کشیدن را روی هر چیزی که بخشی از طرح فعلی نیست رها کند. اگر شنونده با موفقیت حذف را پردازش کند، مقدار بولی |
ACTION_DRAG_ENDED | سیستم در حال پایان دادن به عملیات کشیدن و رها کردن است. این نوع عمل لزوماً با رویداد ACTION_DROP همراه نیست. اگر سیستم یک ACTION_DROP ارسال کند، دریافت نوع عمل ACTION_DRAG_ENDED به معنای موفقیتآمیز بودن عمل رها کردن نیست. شنونده باید getResult() را، همانطور که در جدول 2 نشان داده شده است، فراخوانی کند تا مقداری را که در پاسخ به ACTION_DROP برگردانده میشود، دریافت کند. اگر رویداد ACTION_DROP ارسال نشود، getResult() false را برمیگرداند. |
شیء DragEvent همچنین شامل دادهها و فرادادههایی است که برنامه شما در فراخوانی startDragAndDrop() به سیستم ارائه میدهد. برخی از دادهها فقط برای انواع خاصی از اقدامات معتبر هستند، همانطور که در جدول 2 خلاصه شده است. برای اطلاعات بیشتر در مورد رویدادها و دادههای مرتبط با آنها، به بخشی با عنوان «عملیات کشیدن و رها کردن» مراجعه کنید.
جدول 2. دادههای معتبر DragEvent بر اساس نوع عمل
getAction()ارزش | getClipDescription()ارزش | getLocalState()ارزش | getX()ارزش | getY()ارزش | getClipData()ارزش | getResult()ارزش |
|---|---|---|---|---|---|---|
ACTION_DRAG_STARTED | ✓ | ✓ | ||||
ACTION_DRAG_ENTERED | ✓ | ✓ | ||||
ACTION_DRAG_LOCATION | ✓ | ✓ | ✓ | ✓ | ||
ACTION_DRAG_EXITED | ✓ | ✓ | ||||
ACTION_DROP | ✓ | ✓ | ✓ | ✓ | ✓ | |
ACTION_DRAG_ENDED | ✓ | ✓ |
متدهای DragEvent getAction() ، describeContents() ، writeToParcel() و toString() همیشه دادههای معتبر را برمیگردانند.
اگر یک متد حاوی دادههای معتبر برای یک نوع عمل خاص نباشد، بسته به نوع نتیجهاش، null یا 0 را برمیگرداند.
سایه را بکشید
در طول عملیات کشیدن و رها کردن، سیستم تصویری را که کاربر میکشد نمایش میدهد. برای جابجایی دادهها، این تصویر نشاندهنده دادههای در حال کشیدن است. برای سایر عملیات، تصویر نشاندهنده جنبهای از عملیات کشیدن است.
این تصویر، سایهی کشیدن (drag shadow) نامیده میشود. شما آن را با متدهایی که برای شیء View.DragShadowBuilder تعریف میکنید، ایجاد میکنید. شما سازنده (builder) را هنگام شروع عملیات کشیدن و رها کردن با استفاده از startDragAndDrop() به سیستم ارسال میکنید. به عنوان بخشی از پاسخ خود به startDragAndDrop() ، سیستم متدهای فراخوانی (callback) را که در View.DragShadowBuilder تعریف کردهاید، برای به دست آوردن سایهی کشیدن، فراخوانی میکند.
کلاس View.DragShadowBuilder دو سازنده دارد:
-
View.DragShadowBuilder(View) این سازنده هر یک از اشیاء
Viewبرنامه شما را میپذیرد. سازنده، شیءViewرا در شیءView.DragShadowBuilderذخیره میکند، بنابراین callbackها میتوانند برای ساخت سایه drag به آن دسترسی داشته باشند. view لازم نیستViewای باشد که کاربر برای شروع عملیات drag انتخاب میکند.اگر از این سازنده استفاده کنید، لازم نیست
View.DragShadowBuilderبسط دهید یا متدهای آن را لغو کنید. به طور پیشفرض، یک سایهی کشیدن دریافت میکنید که ظاهری مشابهViewکه به عنوان آرگومان به آن ارسال میکنید، دارد و در مرکز محلی که کاربر صفحه را لمس میکند، قرار میگیرد.-
View.DragShadowBuilder() اگر از این سازنده استفاده کنید، هیچ شیء
Viewدر شیءView.DragShadowBuilderدر دسترس نخواهد بود. این فیلد رویnullتنظیم شده است. شما بایدView.DragShadowBuilderبسط داده و متدهای آن را بازنویسی کنید، در غیر این صورت یک سایه کشیدن نامرئی دریافت خواهید کرد. سیستم خطایی نشان نمیدهد.
کلاس View.DragShadowBuilder دو متد دارد که با هم سایهی درگ را ایجاد میکنند:
-
onProvideShadowMetrics() سیستم بلافاصله پس از فراخوانی
startDragAndDrop()توسط شما، این متد را فراخوانی میکند. از این متد برای ارسال ابعاد و نقطه تماس سایه درگ به سیستم استفاده کنید. این متد دو پارامتر دارد:outShadowSize: یک شیءPoint. عرض سایهی درگ شده بر حسبxو ارتفاع آن بر حسبyاست.outShadowTouchPoint: یک شیءPoint. نقطه لمسی، مکانی درون سایه کشیدن است که باید در حین کشیدن، زیر انگشت کاربر باشد. موقعیت X آن درxو موقعیت Y آن درyقرار میگیرد.-
onDrawShadow() بلافاصله پس از فراخوانی
onProvideShadowMetrics()سیستمonDrawShadow()را برای ایجاد سایه کشیدن فراخوانی میکند. این متد یک آرگومان واحد دارد، یک شیءCanvasکه سیستم از پارامترهایی که شما درonProvideShadowMetrics()ارائه میدهید، میسازد. این متد سایه کشیدن را رویCanvasارائه شده رسم میکند.
برای بهبود عملکرد، اندازه سایه کشیدن را کوچک نگه دارید. برای یک مورد، ممکن است بخواهید از یک آیکون استفاده کنید. برای انتخاب چند مورد، ممکن است بخواهید از آیکونها در یک پشته به جای تصاویر کامل که در صفحه پخش شدهاند، استفاده کنید.
شنوندگان رویداد و متدهای فراخوانی را بکشید
یک View رویدادهای drag را با یک شنوندهی رویداد drag که View.OnDragListener را پیادهسازی میکند یا با متد فراخوانی onDragEvent() مربوط به view دریافت میکند. وقتی سیستم متد یا شنونده را فراخوانی میکند، یک آرگومان DragEvent ارائه میدهد.
در بیشتر موارد، استفاده از یک شنونده (listener) نسبت به استفاده از متد callback ارجحیت دارد. هنگام طراحی رابطهای کاربری، معمولاً از کلاسهای View زیرکلاس نمیسازید، اما استفاده از متد callback شما را مجبور میکند تا زیرکلاسهایی برای لغو متد ایجاد کنید. در مقابل، میتوانید یک کلاس شنونده (listener) را پیادهسازی کنید و سپس آن را با چندین شیء View مختلف استفاده کنید. همچنین میتوانید آن را به عنوان یک کلاس درونخطی ناشناس یا عبارت lambda پیادهسازی کنید. برای تنظیم شنونده برای یک شیء View ، تابع setOnDragListener() را فراخوانی کنید.
به عنوان یک جایگزین، میتوانید پیادهسازی پیشفرض onDragEvent() را بدون بازنویسی متد تغییر دهید. یک OnReceiveContentListener روی یک نما تنظیم کنید؛ برای جزئیات بیشتر، به setOnReceiveContentListener() مراجعه کنید. سپس متد onDragEvent() به طور پیشفرض موارد زیر را انجام میدهد:
- در پاسخ به فراخوانی تابع
startDragAndDrop()مقدار true را برمیگرداند. اگر دادههای حاصل از کشیدن و رها کردن در نما رها شوند، تابع
performReceiveContent()فراخوانی میشود. دادهها به عنوان یک شیءContentInfoبه متد ارسال میشوند. متد،OnReceiveContentListenerرا فراخوانی میکند.اگر دادههای کشیدن و رها کردن روی نما رها شوند و
OnReceiveContentListenerهر یک از محتوا را مصرف کند، مقدار true را برمیگرداند.
OnReceiveContentListener برای مدیریت دادهها به طور خاص برای برنامه خود تعریف کنید. برای سازگاری با نسخههای قبلی تا سطح API 24، از نسخه Jetpack از OnReceiveContentListener استفاده کنید.
شما میتوانید یک شنوندهی رویداد drag و یک متد callback برای یک شیء View داشته باشید، که در این صورت سیستم ابتدا شنونده را فراخوانی میکند. سیستم متد callback را فراخوانی نمیکند مگر اینکه شنونده false را برگرداند.
ترکیب متد onDragEvent() و View.OnDragListener مشابه ترکیب onTouchEvent() و View.OnTouchListener است که در رویدادهای لمسی استفاده میشود.
