تشرح الأقسام التالية بعض المفاهيم الأساسية لعملية السحب والإفلات.
عملية السحب والإفلات
هناك أربع خطوات أو حالات في عملية السحب والإفلات: البدء والاستمرار والإفلات والإنهاء.
- تم بدء التنفيذ.
استجابةً لإيماءة السحب التي أجراها المستخدم، يطلب تطبيقك الرمز
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
والموضّحة في الجدول 1:
نوع الإجراء | المعنى |
---|---|
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 إلا إذا كان المستمع يعرض قيمة true المنطقية كاستجابة لحدث السحب ACTION_DRAG_STARTED . لا يتم إرسال نوع الإجراء هذا
إذا أطلق المستخدم ظل السحب على View
الذي لم يتم تسجيل أداة الاستماع إليه أو إذا أطلق المستخدم ظل السحب
على أي عنصر ليس جزءًا من التنسيق الحالي.
يعرض المستمع |
ACTION_DRAG_ENDED |
يُنهي النظام عملية السحب والإفلات. ليس بالضرورة أن يكون نوع الإجراء هذا مسبوقًا بحدث ACTION_DROP . إذا
أرسل النظام ACTION_DROP ، لن يعني تلقّي
نوع الإجراء ACTION_DRAG_ENDED أنّه تم الانخفاض بنجاح. على المستمع طلب getResult() ، كما هو موضّح في الجدول 2، للحصول على القيمة التي يتم عرضها استجابةً للسمة ACTION_DROP . إذا لم يتم إرسال حدث ACTION_DROP ، ستعرض السمة getResult() القيمة false .
|
يحتوي الكائن DragEvent
أيضًا على البيانات والبيانات الوصفية التي يوفّرها تطبيقك للنظام في طلب startDragAndDrop()
. بعض البيانات صالحة فقط لأنواع إجراءات معينة
كما هو موضح في الجدول 2. لمزيد من المعلومات حول الأحداث والبيانات المرتبطة بها، يمكنك الاطّلاع على قسم عملية السحب والإفلات.
قيمة 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، بناءً على نوع النتيجة.
سحب الظل
أثناء عملية السحب والإفلات، يعرض النظام صورة يسحبها المستخدم. بالنسبة إلى حركة البيانات، تمثل هذه الصورة البيانات التي يتم سحبها. بالنسبة للعمليات الأخرى، تمثل الصورة بعض جوانب عملية السحب.
يُطلق على الصورة ظل السحب. يمكنك إنشاؤها باستخدام الطرق التي تعلن عنها
لكائن
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
الفرعية، ولكن استخدام طريقة معاودة الاتصال يفرض عليك إنشاء فئات فرعية لإلغاء الطريقة. وبالمقارنة، يمكنك تطبيق فئة مستمع واحدة ثم استخدامها مع عدة كائنات View
مختلفة. يمكنك أيضًا تنفيذه كتعبير مضمّن
مجهول الهوية أو تعبير lambda. لضبط أداة المستمع لكائن View
، يمكنك طلب
setOnDragListener()
.
كخيار بديل، يمكنك تغيير طريقة التنفيذ التلقائية للسمة onDragEvent()
بدون إلغاء الطريقة. اضبط
OnReceiveContentListener
على عرض. لمزيد من التفاصيل، راجِع
setOnReceiveContentListener()
.
بعد ذلك، تنفِّذ الطريقة onDragEvent()
ما يلي تلقائيًا:
- يتم عرض القيمة "صحيح" استجابةً للمكالمة الواردة إلى
startDragAndDrop()
. استدعاء
performReceiveContent()
إذا تم إسقاط بيانات السحب والإفلات في العرض. يتم تمرير البيانات إلى الطريقة ككائنContentInfo
. تستدعي الطريقةOnReceiveContentListener
.يتم عرض القيمة "صحيح" إذا تم إسقاط بيانات السحب والإفلات في العرض وكان
OnReceiveContentListener
يستهلك أيًا من المحتوى.
حدِّد OnReceiveContentListener
لمعالجة بيانات تطبيقك تحديدًا. للتوافق مع الأنظمة القديمة وصولاً إلى المستوى 24 من واجهة برمجة التطبيقات، استخدِم إصدار Jetpack من
OnReceiveContentListener
.
يمكنك استخدام أداة معالجة حدث السحب وطريقة لمعاودة الاتصال لكائن View
، وفي هذه الحالة يطلب النظام المستمع أولاً. ولا يستدعي النظام طريقة معاودة الاتصال ما لم يعرض المستمع false
.
يُشابه الجمع بين طريقة onDragEvent()
وView.OnDragListener
للجمع بين onTouchEvent()
وView.OnTouchListener
المستخدَمين مع أحداث اللمس.