בקטעים הבאים מוסברים כמה מושגים חשובים לגבי תהליך הגרירה וההדבקה.
תהליך הגרירה והשחרור
יש ארבעה שלבים או מצבים בתהליך הגרירה והשחרור: התחלה, המשך, שחרור וסיום.
- התחיל
בתגובה לתנועת גרירה של משתמש, האפליקציה שלכם קוראת ל-
startDragAndDrop()כדי להודיע למערכת להתחיל פעולת גרירה ושחרור. הארגומנטים של השיטה מספקים את הפרטים הבאים:- הנתונים שרוצים לגרור.
- קריאה חוזרת (callback) לציור צללית גרירה
- מטא-נתונים שמתארים את הנתונים שנגררו
- המערכת מגיבה בקריאה חוזרת לאפליקציה כדי לקבל צל של גרירה. לאחר מכן, המערכת מציגה את צללית הגרירה במכשיר.
- לאחר מכן, המערכת שולחת אירוע גרירה עם סוג הפעולה
ACTION_DRAG_STARTEDלמאזין של אירוע הגרירה של כל האובייקטיםViewבפריסה הנוכחית. כדי להמשיך לקבל אירועי גרירה – כולל אירוע אפשרי של שחרור – פונקציית ה-event listener של הגרירה צריכה להחזירtrue. הפעולה הזו רושמת את מאזין האירועים במערכת. רק משתמשי listener רשומים ממשיכים לקבל אירועי גרירה. בשלב הזה, המאזינים יכולים גם לשנות את המראה של אובייקטViewהיעד לגרירה כדי להראות שאפשר להוסיף אירוע גרירה לתצוגה. - אם מאזין אירועי הגרירה מחזיר
false, הוא לא מקבל אירועי גרירה עבור הפעולה הנוכחית עד שהמערכת שולחת אירוע גרירה עם סוג הפעולהACTION_DRAG_ENDED. החזרת הערךfalseעל ידי ה-listener מציינת למערכת שהוא לא מעוניין בפעולת הגרירה וההעברה, ושהוא לא רוצה לקבל את הנתונים שנגררו.
- התהליך נמשך…
- המשתמש ממשיך לגרור. כשצל הגרירה חוצה את התיבה התוחמת של יעד השחרור, המערכת שולחת אירוע גרירה אחד או יותר אל פונקציית ה-event listener של הגרירה של היעד. יכול להיות שה-listener ישנה את המראה של אזור היעד
Viewבתגובה לאירוע. לדוגמה, אם האירוע מציין שצללית הגרירה נכנסת לתיבה התוחמת של יעד השחרור – סוג הפעולהACTION_DRAG_ENTERED– אפשר להגדיר את ה-listener כך שיגיב על ידי הדגשתView. - בוטל
- המשתמש משחרר את צללית הגרירה בתוך התיבה התוחמת של יעד השחרור. המערכת שולחת ל-listener של אזור היעד של הגרירה אירוע גרירה עם סוג הפעולה
ACTION_DROP. אובייקט אירוע הגרירה מכיל את הנתונים שמועברים למערכת בקריאה ל-startDragAndDrop()שמתחילה את הפעולה. המאזין אמור להחזיר למערכת ערך בוליאניtrueאם הוא מעבד את הנתונים שהועברו בהצלחה. : השלב הזה מתרחש רק אם המשתמש משחרר את הצללית של הגרירה בתוך תיבת התוחמת שלViewשהמאזין שלה רשום לקבלת אירועי גרירה (יעד השחרור). אם המשתמש משחרר את צללית הגרירה בכל מצב אחר, לא נשלחACTION_DROPאירוע גרירה .
- הסתיים
אחרי שהמשתמש משחרר את צללית הגרירה, ואחרי שהמערכת שולחת
אם צריך, המערכת שולחת אירוע גרירה עם סוג הפעולה
ACTION_DRAG_ENDEDכדי לציין שפעולת הגרירה הסתיימה.ACTION_DROPהפעולה הזו מתבצעת בלי קשר למיקום שבו המשתמש משחרר את צללית הגרירה. האירוע נשלח לכל פונקציית listener שרשומה לקבלת אירועי גרירה, גם אם הפונקציה מקבלת גם את האירועACTION_DROP.
כל אחד מהשלבים האלה מתואר בפירוט בקטע פעולת גרירה ושחרור.
גרירת אירועים
המערכת שולחת אירוע גרירה בצורה של אובייקט DragEvent, שמכיל סוג פעולה שמתאר מה קורה בתהליך הגרירה וההשלכה. בהתאם לסוג הפעולה, האובייקט יכול להכיל גם נתונים אחרים.
פונקציות event listener של גרירה מקבלות את האובייקט DragEvent. כדי לקבל את סוג הפעולה, המאזינים מתקשרים למספר DragEvent.getAction().
יש שישה ערכים אפשריים שמוגדרים על ידי קבועים במחלקה DragEvent, שמתוארים בטבלה 1:
טבלה 1. סוגי פעולות של DragEvent
| סוג הפעולה | משמעות |
|---|---|
ACTION_DRAG_STARTED |
האפליקציה קוראת ל-startDragAndDrop() ומקבלת
צללית גרירה. אם המאזין רוצה להמשיך לקבל אירועי גרירה עבור הפעולה הזו, הוא צריך להחזיר למערכת את הערך הבוליאני true.
|
ACTION_DRAG_ENTERED |
צללית גרירה נכנסת לתיבה התוחמת של View של ה-drag event listener. זהו סוג הפעולה הראשון של האירוע שהמאזין מקבל כשצל הגרירה נכנס לתיבת התוחמת.
|
ACTION_DRAG_LOCATION |
אחרי אירוע ACTION_DRAG_ENTERED, צללית הגרירה עדיין נמצאת בתיבה התוחמת של View של drag event listener של הגרירה.
|
ACTION_DRAG_EXITED |
אחרי אירוע ACTION_DRAG_ENTERED ולפחות אירוע ACTION_DRAG_LOCATION אחד, הצללית של הגרירה עוברת אל מחוץ לתיבת התוחמת של View של מאזין אירועי הגרירה.
|
ACTION_DROP |
צללית הגרירה משתחררת מעל View של ה-drag event listener. סוג הפעולה הזה נשלח ל-listener של אובייקט View רק אם ה-listener מחזיר ערך בוליאני true בתגובה לאירוע הגרירה ACTION_DRAG_STARTED. סוג הפעולה הזה לא נשלח אם המשתמש משחרר את צללית הגרירה מעל רכיב שרכיב ה-listener שלו לא רשום, או אם המשתמש משחרר את צללית הגרירה מעל משהו שלא שייך לפריסה הנוכחית.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()value |
getClipDescription()value |
getLocalState()value |
getX()value |
getY()value |
getClipData()value |
getResult()value |
|---|---|---|---|---|---|---|
ACTION_DRAG_STARTED |
✓ | ✓ | ||||
ACTION_DRAG_ENTERED |
✓ | ✓ | ||||
ACTION_DRAG_LOCATION |
✓ | ✓ | ✓ | ✓ | ||
ACTION_DRAG_EXITED |
✓ | ✓ | ||||
ACTION_DROP |
✓ | ✓ | ✓ | ✓ | ✓ | |
ACTION_DRAG_ENDED |
✓ | ✓ |
השיטות DragEvent getAction(),
describeContents(),
writeToParcel(),
ו-toString() תמיד מחזירות נתונים תקינים.
אם שיטה לא מכילה נתונים תקינים לסוג פעולה מסוים, היא מחזירה null או 0, בהתאם לסוג התוצאה שלה.
צללית גרירה
במהלך פעולת גרירה ושחרור, המערכת מציגה תמונה שהמשתמש גורר. בתמונה הזו, שמייצגת העברת נתונים, רואים את הנתונים שנגררים. בפעולות אחרות, התמונה מייצגת היבט מסוים של פעולת הגרירה.
התמונה נקראת צללית גרירה. יוצרים אותו באמצעות methods שמצהירים עליהם באובייקט View.DragShadowBuilder. מעבירים את הכלי למערכת כשמתחילים פעולת גרירה ושחרור באמצעות startDragAndDrop(). כחלק מהתגובה ל-startDragAndDrop(), המערכת מפעילה את שיטות הקריאה החוזרת שהגדרתם ב-View.DragShadowBuilder כדי לקבל צללית של הגרירה.
למחלקת View.DragShadowBuilder יש שני בנאים:
View.DragShadowBuilder(View)הבונה הזה מקבל כל אחד מהאובייקטים של
Viewבאפליקציה. ה-constructor מאחסן את האובייקטViewבאובייקטView.DragShadowBuilder, כך שפונקציות ה-callback יכולות לגשת אליו כדי ליצור את צללית הגרירה. התצוגה לא חייבת להיותViewשהמשתמש בוחר כדי להתחיל את פעולת הגרירה.אם משתמשים בבונה הזה, לא צריך להרחיב את
View.DragShadowBuilderאו לבטל את השיטות שלו. כברירת מחדל, מקבלים צל גרירה שנראה כמוViewשמועבר כארגומנט, והוא ממוקם במרכז מתחת למיקום שבו המשתמש נוגע במסך.View.DragShadowBuilder()אם משתמשים ב-constructor הזה, אין אובייקט
Viewזמין באובייקטView.DragShadowBuilder. השדה מוגדר ל-null. צריך להרחיב אתView.DragShadowBuilderולשנות את ה-methods שלו, אחרת מתקבל צל גרירה בלתי נראה. המערכת לא מציגה שגיאה.
במחלקת View.DragShadowBuilder יש שתי שיטות שיוצרות יחד את הצללית של הגרירה:
onProvideShadowMetrics()המערכת קוראת ל-method הזה מיד אחרי שקוראים ל-
startDragAndDrop(). משתמשים בשיטה כדי לשלוח את המימדים ואת נקודת המגע של הצללית הגרורה למערכת. ל-method יש שני פרמטרים:
outShadowSize: אובייקטPointהרוחב של צללית הגרירה מופיע ב-x, והגובה שלה מופיע ב-y.
outShadowTouchPoint: אובייקטPoint. נקודת המגע היא המיקום בתוך צללית הגרירה שצריך להיות מתחת לאצבע של המשתמש במהלך הגרירה. המיקום X שלו מופיע ב-xוהמיקום Y שלו מופיע ב-y.onDrawShadow()מיד אחרי הקריאה ל-
onProvideShadowMetrics()המערכת קוראת ל-onDrawShadow()כדי ליצור את צללית הגרירה. ל-method יש ארגומנט יחיד, אובייקטCanvasשהמערכת בונה מהפרמטרים שאתם מספקים ב-onProvideShadowMetrics(). השיטה מציירת את צללית הגרירה ב-Canvasשסופק.
כדי לשפר את הביצועים, כדאי לשמור על גודל קטן של צללית גרירה. אם מדובר בפריט אחד, כדאי להשתמש בסמל. אם בוחרים כמה פריטים, כדאי להשתמש בסמלים בערימה ולא בתמונות מלאות שמוצגות על המסך.
פונקציות event listener ושיטות callback של גרירה
View מקבלת אירועי גרירה באמצעות פונקציית event listener לגרירה שמטמיעה את View.OnDragListener או באמצעות שיטת הקריאה החוזרת onDragEvent() של התצוגה. כשהמערכת קוראת לשיטה או למאזין, היא מספקת ארגומנט DragEvent.
ברוב המקרים, עדיף להשתמש ב-listener מאשר בשיטת הקריאה החוזרת. כשמעצבים ממשקי משתמש, בדרך כלל לא יוצרים מחלקות משנה של מחלקות View, אבל השימוש בשיטת הקריאה החוזרת מחייב אתכם ליצור מחלקות משנה כדי לבטל את השיטה. לעומת זאת, אפשר להטמיע מחלקה אחת של מאזין ואז להשתמש בה עם כמה אובייקטים שונים של View. אפשר גם להטמיע אותו כמחלקה מוטמעת אנונימית או כביטוי למבדה. כדי להגדיר את מאזין לאובייקט View, קוראים ל-setOnDragListener().
אפשר גם לשנות את הטמעת ברירת המחדל של onDragEvent() בלי לבטל את השיטה. הגדרת OnReceiveContentListener בתצוגה. פרטים נוספים זמינים במאמר setOnReceiveContentListener().
השיטה onDragEvent() מבצעת את הפעולות הבאות כברירת מחדל:
- מחזירה את הערך true בתגובה לקריאה אל
startDragAndDrop(). שיחות
performReceiveContent()אם גוררים את הנתונים ומשחררים אותם בתצוגה. הנתונים מועברים לשיטה כאובייקטContentInfo. השיטה מפעילה אתOnReceiveContentListener.הפונקציה מחזירה את הערך true אם נתוני הגרירה והשחרור משוחררים בתצוגה ורכיב
OnReceiveContentListenerצורך חלק מהתוכן.
מגדירים את OnReceiveContentListener כדי לטפל בנתונים באופן ספציפי לאפליקציה. כדי להבטיח תאימות לאחור עד לרמת API 24, משתמשים בגרסת Jetpack של OnReceiveContentListener.
אפשר להגדיר פונקציית drag event listener ושיטת קריאה חוזרת לאובייקט View. במקרה כזה, המערכת קודם קוראת לפונקציית ה-listener. המערכת לא קוראת לשיטת הקריאה החוזרת אלא אם המאזין מחזיר false.
השילוב של השיטה onDragEvent() ושל View.OnDragListener דומה לשילוב של onTouchEvent() ושל View.OnTouchListener שמשמשים לאירועי מגע.