السحب والإفلات

تتيح أداة Jetpack Compose ميزة السحب والإفلات باستخدام مُعدِّلَين:

  • dragAndDropSource: لتحديد عنصر قابل للتجميع كنقطة بداية لإيماءة السحب
  • dragAndDropTarget: لتحديد عنصر قابل للتجميع يقبل data التي تم إسقاطها

على سبيل المثال، لتفعيل ميزة سحب صورة في تطبيقك، أنشئ عنصرًا قابلاً للتركيب وضمِّن المُعدِّل dragAndDropSource. لإعداد هدف إسقاط، أنشئ عنصرًا آخر قابلاً للتركيب من الصور وأضِف المُعدِّل dragAndDropTarget.

يمكن تطبيق المُعدِّلات على مصادر سحب متعددة واستهدافات إسقاط متعددة.

تتيح المُعدِّلات للتطبيقات مشاركة البيانات بين عنصرَين أو أكثر من العناصر القابلة للتجميع باستخدام ClipData، وهو متوافق مع عمليات تنفيذ View.

تحديد مصدر السحب

لتفعيل أحداث السحب داخل مكوّن، أضِف المُعدِّل dragAndDropSource. تأخذ هذه الدالة دالة كمَعلمة. داخل هذه الدالة، استخدِم DragAndDropTransferData لتمثيل البيانات القابلة للنقل. يمكن أن تكون البيانات معرّف موارد منتظم عن بُعد أو بيانات نص غني في الحافظة أو ملف على الجهاز أو غير ذلك، ولكن يجب تضمين كل البيانات في عنصر ClipData. قدِّم نصًا عاديًا، على سبيل المثال، على النحو التالي:

Modifier.dragAndDropSource { _ ->
    DragAndDropTransferData(
        ClipData.newPlainText(
            "image Url", url
        )
    )
}

للسماح للإجراء "السحب" بتجاوز حدود التطبيق، يقبل مُنشئ DragAndDropTransferData وسيطة flags. في المثال التالي، يحدِّد الثابت DRAG_FLAG_GLOBAL أنّه يمكن سحب البيانات من تطبيق إلى آخر:

Modifier.dragAndDropSource { _ ->
    DragAndDropTransferData(
        ClipData.newPlainText(
            "image Url", url
        ),
        flags = View.DRAG_FLAG_GLOBAL
    )
}

DragAndDropTransferData يقبل الإشارات المتوافقة مع نظام Android View. اطّلِع على قائمة ثوابت View للحصول على قائمة شاملة بالعلامات المتاحة.

تلقّي بيانات عمليات الطرح

يمكنك تعيين المُعدِّل dragAndDropTarget إلى عنصر قابل للتجميع لتفعيل العنصر القابل للتجميع لتلقّي أحداث السحب والإفلات. يحتوي المُعدِّل على مَعلمتَين: الأولى تعمل كهيأة فلتر وتحدِّد نوع البيانات التي يمكن للمُعدِّل قبولها، والثانية تُرسِل البيانات في ردّ اتصال.

يُرجى العلم أنّه يجب تذكُّر مثيل طلب معاودة الاتصال. توضِّح المقتطف التالي كيفية تذكُّر طلب معاودة الاتصال:

val callback = remember {
    object : DragAndDropTarget {
        override fun onDrop(event: DragAndDropEvent): Boolean {
            // Parse received data
            return true
        }
    }
}

لقبول البيانات من تطبيقات أخرى، استخدِم الرمز requestDragAndDropPermission ل تفعيل الاستقبال، ثم ارفع إصبعك عن الشاشة بعد الانتهاء:

val externalAppCallback = remember {
    object : DragAndDropTarget {
        override fun onDrop(event: DragAndDropEvent): Boolean {
            val permission =
                activity.requestDragAndDropPermissions(event.toAndroidDragEvent())
            // Parse received data
            permission?.release()
            return true
        }
    }
}

من المهم تذكُّر أنّ القيمة DragAndDropEvent التي يتم إرجاعها من دالة الردّ requestDragAndDropPermission تختلف عن القيمة المتوقّعة من الدالة requestDragAndDropPermission ، لذا عليك استدعاء دالة التوسيع toAndroidDragEvent() على المَعلمة قبل إرسالها إلى طلب الإذن.

يوضّح المقتطف التالي كيفية التعامل مع النص العادي الذي تم إسقاطه:

Modifier.dragAndDropTarget(
    shouldStartDragAndDrop = { event ->
        event.mimeTypes().contains(ClipDescription.MIMETYPE_TEXT_PLAIN)
    }, target = callback // or externalAppCallback
)

يجب أن تعرِض دالة الاستدعاء القيمة true في حال استخدام الحدث، أو القيمة false في حال رفض الحدث وعدم نشره إلى المكوّن الرئيسي.

التعامل مع أحداث السحب والإفلات

يمكنك إلغاء عمليات الاستدعاء في واجهة DragAndDropTarget لمراقبة بدء حدث السحب والإفلات أو انتهائه أو دخوله إلى مكوّن أو خروجه منه من أجل التحكّم بدقة في واجهة المستخدم وسلوك التطبيق:

object : DragAndDropTarget {
    override fun onStarted(event: DragAndDropEvent) {
        // When the drag event starts
    }

    override fun onEntered(event: DragAndDropEvent) {
        // When the dragged object enters the target surface
    }

    override fun onEnded(event: DragAndDropEvent) {
        // When the drag event stops
    }

    override fun onExited(event: DragAndDropEvent) {
        // When the dragged object exits the target surface
    }

    override fun onDrop(event: DragAndDropEvent): Boolean = true
}

مراجع إضافية

الدرس التطبيقي حول الترميز: السحب والإفلات في ميزة "الإنشاء"