גרירה ושחרור

ב-Jetpack Compose אפשר להשתמש בגרירה ושחרור באמצעות שני משתני שינוי:

  • ‫dragAndDropSource: מציין פונקציה קומפוזבילית כנקודת ההתחלה של תנועת הגרירה
  • ‫dragAndDropTarget: מציין פונקציה קומפוזבילית שמקבלת את הנתונים ששוחררו

לדוגמה, כדי לאפשר למשתמשים לגרור תמונה באפליקציה, יוצרים פונקציה קומפוזבילית של תמונה ומוסיפים את העיבוד dragAndDropSource. כדי להגדיר יעד להשלכה, יוצרים עוד רכיב תמונה ומוסיפים את המשתנה dragAndDropTarget.

אפשר להחיל את מקשי הצירופים על כמה מקורות גרירה וכמה יעדי שחרור.

המשתנים מאפשרים לאפליקציות לשתף נתונים בין שני רכיבים או יותר שניתנים ליצירה באמצעות ClipData, שפועל בשילוב עם הטמעות של View.

ציון מקור הגרירה

כדי להפעיל אירועי גרירה בתוך רכיב, מוסיפים את המשתנה dragAndDropSource. הוא מקבל פונקציה כפרמטר. בתוך הפונקציה הזו, משתמשים ב-DragAndDropTransferData כדי לייצג את הנתונים שניתן להעביר. הנתונים יכולים להיות URI מרוחק, נתוני טקסט עשיר בלוח, קובץ מקומי ועוד, אבל כולם צריכים להיות עטופים באובייקט ClipData. לדוגמה, אפשר להזין טקסט פשוט:

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

כדי לאפשר לפעולת הגרירה לחצות את גבולות האפליקציה, ה-constructor של DragAndDropTransferData מקבל ארגומנט של flags. בדוגמה הבאה, הקבוע DRAG_FLAG_GLOBAL מציין שאפשר לגרור נתונים מאפליקציה אחת לאחרת:

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

‫DragAndDropTransferData מקבל דגלים שנתמכים על ידי מערכת Android View. רשימה מלאה של הדגלים הזמינים מופיעה ברשימת הקבועים של View.

קבלת נתוני שחרור

מקצים את המשתנה dragAndDropTarget לרכיב ה-composable כדי לאפשר לו לקבל אירועי גרירה ושחרור. למשתנה יש שני פרמטרים: הראשון פועל כמסנן ומציין את סוג הנתונים שהמשתנה יכול לקבל, והשני מעביר את הנתונים בקריאה חוזרת (callback).

חשוב לזכור שצריך לזכור את המופע של הקריאה החוזרת. בקטע הקוד הבא אפשר לראות איך לזכור את הקריאה החוזרת:

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 שמוחזר מה-callback של Compose שונה מהערך שצפוי מה-method‏ requestDragAndDropPermission, לכן צריך להפעיל את פונקציית התוסף toAndroidDragEvent() בפרמטר לפני שמעבירים אותו לבקשת ההרשאה.

בקטע הקוד הבא אפשר לראות איך מטפלים בטקסט פשוט שנגרר:

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

פונקציית הקריאה החוזרת צריכה להחזיר true אם האירוע נצרך, או false אם האירוע נדחה ולא מופץ לרכיב ההורה.

טיפול באירועי גרירה ושחרור

כדי לשלוט בצורה מדויקת בממשק המשתמש ובהתנהגות של האפליקציה, אפשר לשנות את הקריאות החוזרות (callbacks) בממשק 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
}

מקורות מידע נוספים

‫Codelab: גרירה ושחרור בפיתוח נייטיב