در بخشهای زیر، چند مفهوم کلیدی برای فرایند کشیدن و رها کردن توضیح داده شده است.
فرایند کشیدن و رها کردن
در فرایند کشیدن و رها کردن، چهار مرحله یا حالت وجود دارد: شروعشده، ادامهدار، رهاشده، و پایانیافته.
- شروع شد
در پاسخ به اشاره کشیدن کاربر، برنامه شما
startDragAndDrop()را فراخوانی میکند تا به سیستم بگوید عملیات کشیدن و رها کردن را شروع کند. متغیرهای مستقل روش موارد زیر را ارائه میدهند:- دادههایی که باید کشیده شود.
- یک فراخوانی برگشتی برای ترسیم سایه کشیدن
- فرادادهای که دادههای کشیدهشده را توصیف میکند
- سیستم با فراخوانی مجدد برنامه شما برای دریافت سایه کشیدن پاسخ میدهد. سپس سیستم سایه کشیدن را در دستگاه نمایش میدهد.
- سپس، سیستم رویداد کشیدنی با نوع کنش
ACTION_DRAG_STARTEDبه شنونده رویداد کشیدن همه اشیایViewدر چیدمان فعلی ارسال میکند. برای ادامه دریافت رویدادهای کشیدن (ازجمله رویداد احتمالی رها کردن)، شنونده رویداد کشیدن بایدtrueرا برگرداند. این کار شنونده را در سیستم ثبت میکند. فقط شنوندگان ثبتشده همچنان رویدادهای کشیدن را دریافت میکنند. در این مرحله، شنوندگان همچنین میتوانند ظاهر شیء هدف رها کردن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را نیز دریافت کند.
هرکدام از این مراحل با جزئیات بیشتر در بخش عملیات کشیدن و رها کردن شرح داده شده است.
رویدادهای کشیدن
سیستم رویداد کشیدن را بهصورت شیء DragEvent ارسال میکند که حاوی نوع کنشی است که آنچه را در فرایند کشیدن و رها کردن اتفاق میافتد شرح میدهد. بسته به نوع کنش، شیء میتواند حاوی دادههای دیگری نیز باشد.
شنوندگان رویداد کشیدن شیء DragEvent را دریافت میکنند. برای دریافت نوع کنش،
شنوندگان با
DragEvent.getAction() تماس میگیرند.
شش مقدار ممکن وجود دارد که توسط ثابتها در کلاس DragEvent تعریف شدهاند،
که در جدول ۱ شرح داده شدهاند:
جدول ۱. انواع کنش DragEvent
| نوع اقدام | معنی |
|---|---|
ACTION_DRAG_STARTED |
برنامه startDragAndDrop() را فراخوانی میکند و
سایه کشیدن را دریافت میکند. اگر شنونده بخواهد همچنان رویدادهای کشیدن را برای این عملیات دریافت کند، باید مقدار بولی true را به سیستم برگرداند.
|
ACTION_DRAG_ENTERED |
سایه کشیدن وارد کادر مرزی View شنونده رویداد کشیدن میشود. این اولین نوع کنش رویدادی است که شنونده
هنگام ورود سایه کشیدن به کادر مرزی دریافت میکند.
|
ACTION_DRAG_LOCATION |
پساز رویداد
ACTION_DRAG_ENTERED، سایه کشیدن هنوز
درون کادر مرزی
View شنونده رویداد کشیدن است.
|
ACTION_DRAG_EXITED |
بهدنبال یک ACTION_DRAG_ENTERED و حداقل یک رویداد ACTION_DRAG_LOCATION، سایه کشیدن به خارج از کادر محدودکننده View شنونده رویداد کشیدن منتقل میشود.
|
ACTION_DROP |
سایه کشیدن روی View شنونده رویداد کشیدن رها میشود. این نوع کنش فقط درصورتی به شنونده شیء View ارسال میشود که شنونده در پاسخ به رویداد کشیدن ACTION_DRAG_STARTED، بولی true را برگرداند. اگر کاربر سایه کشیدن را روی View که شنونده آن ثبت نشده است رها کند، یا اگر کاربر سایه کشیدن را روی چیزی که بخشی از چیدمان فعلی نیست رها کند، این نوع کنش ارسال نمیشود.
اگر شنونده رها کردن را باموفقیت پردازش کند،
مقدار بولی |
ACTION_DRAG_ENDED |
The system is ending the drag-and-drop operation. این نوع کنش
لزوماً با رویداد ACTION_DROP پیشبرده نمیشود. اگر
سیستم ACTION_DROP ارسال کند، دریافت
نوع کنش ACTION_DRAG_ENDED بهمعنای موفقیتآمیز بودن
رها کردن نیست. شنونده باید
getResult() را فراخوانی کند،
همانطور که در جدول ۲ نشان داده شده است، تا مقداری را که
در پاسخ به ACTION_DROP برگردانده میشود دریافت کند. اگر
رویداد ACTION_DROP ارسال نشود،
getResult() false را برمیگرداند.
|
شیء DragEvent همچنین حاوی دادهها و فرادادههایی است که برنامه شما
در تماس با startDragAndDrop() به سیستم ارائه میدهد. برخیاز دادهها
فقط برای انواع کنشهای خاصی معتبر است که در جدول ۲ خلاصه شده است. برای اطلاعات بیشتر درباره رویدادها و دادههای مرتبط با آنها، به بخش عملیات کشیدن و رها کردن مراجعه کنید.
جدول ۲. دادههای 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 یا ۰ را برمیگرداند.
سایه کشیدن
درطول عملیات کشیدن و رها کردن، سیستم تصویری را نمایش میدهد که کاربر میکشد. برای جابهجایی دادهها، این تصویر نشاندهنده دادههایی است که کشیده میشوند. برای عملیاتهای دیگر، تصویر نشاندهنده جنبهای از عملیات کشیدن است.
به این تصویر سایه کشیدن میگویند. آن را با روشهایی که برای شیء
View.DragShadowBuilder
اعلام میکنید ایجاد میکنید. وقتی عملیات کشیدن و رها کردن را بااستفاده از startDragAndDrop() شروع میکنید، سازنده را به سیستم منتقل میکنید. بهعنوان بخشی از پاسخ به
startDragAndDrop()، سیستم روشهای فراخوانی را که در
View.DragShadowBuilder تعریف میکنید برای دریافت سایه کشیدن فراخوانی میکند.
کلاس View.DragShadowBuilder دو سازنده دارد:
View.DragShadowBuilder(View)این سازنده هریک از اشیاء
Viewبرنامهتان را میپذیرد. سازنده شیءViewرا در شیءView.DragShadowBuilderذخیره میکند تا فراخوانیهای برگشتی بتوانند برای ساختن سایه کشیدن به آن دسترسی داشته باشند. لازم نیست نماViewباشد که کاربر برای شروع عملیات کشیدن انتخاب میکند.اگر از این سازنده استفاده میکنید، لازم نیست
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 رویدادهای کشیدن را با شنونده رویداد کشیدن که
View.OnDragListener را پیادهسازی میکند یا با روش فراخوانی برگشتی onDragEvent() نما دریافت میکند. وقتی
سیستم متد یا شنونده را فراخوانی میکند، آرگومان
DragEvent را ارائه میدهد.
در بیشتر موارد، استفاده از شنونده بر استفاده از روش فراخوانی برگشتی ترجیح داده میشود. وقتی
رابطهای کاربری را طراحی میکنید، معمولاً کلاسهای View را زیرکلاس نمیکنید، اما استفاده از
روش callback شما را مجبور میکند تا زیرکلاسهایی برای لغو روش ایجاد کنید. درمقایسه، میتوانید یک کلاس شنونده را پیادهسازی کنید و سپس از آن با چندین شیء View مختلف استفاده کنید. همچنین میتوانید آن را بهعنوان کلاس درونخطی ناشناس
یا عبارت لامبدا پیادهسازی کنید. برای تنظیم شنونده برای شیء View،
setOnDragListener() را فراخوانی کنید.
بهعنوان جایگزین، میتوانید پیادهسازی پیشفرض onDragEvent() را بدون لغو کردن روش تغییر دهید. OnReceiveContentListener
را در نمای موردنظر تنظیم کنید؛ برای جزئیات بیشتر،
setOnReceiveContentListener()
را ببینید.
سپس روش onDragEvent() بهطور پیشفرض کارهای زیر را انجام میدهد:
- در پاسخ به تماس با
startDragAndDrop()، مقدار true را برمیگرداند. فراخوانی میکند
performReceiveContent()اگر دادههای کشیدن و رها کردن در نما رها شود. دادهها بهعنوان شیءContentInfoبه روش منتقل میشوند. روشOnReceiveContentListenerرا فراخوانی میکند.اگر دادههای کشیدن و رها کردن در نما رها شود و
OnReceiveContentListenerهریک از محتواها را مصرف کند، مقدار «درست» برمیگرداند.
OnReceiveContentListener را برای مدیریت دادهها بهطور خاص برای برنامهتان تعریف کنید. برای سازگاری با نسخههای قدیمی تا سطح API ۲۴، از نسخه Jetpack OnReceiveContentListener استفاده کنید.
میتوانید یک شنونده رویداد کشیدن و یک روش فراخوانی برگشتی برای شیء View داشته باشید، که در این صورت سیستم ابتدا شنونده را فراخوانی میکند. سیستم روش فراخوانی را فراخوانی نمیکند مگر اینکه شنونده false را برگرداند.
ترکیب روش onDragEvent() و View.OnDragListener
مشابه ترکیب
onTouchEvent()
و View.OnTouchListener
است که با رویدادهای لمسی استفاده میشود.