בקטעים הבאים מוסבר על כמה מושגים מרכזיים בתהליך של גרירה ושחרור.
תהליך הגרירה והשחרור
יש ארבעה שלבים או מצבים בתהליך הגרירה והשחרור: 'התחלה', 'המשך', 'שחרור' ו'סיום'.
- ספרים שהתחלת
בתגובה לתנועת גרירה של משתמש, האפליקציה קוראת ל-
startDragAndDrop()
כדי להודיע למערכת להתחיל פעולת גרירה ושחרור. הארגומנטים של השיטה מספקים את הפרטים הבאים:- הנתונים שרוצים לגרור.
- קריאה חוזרת (callback) לציור הצללית של הגרירה
- מטא-נתונים שמתארים את הנתונים שנגררו
- המערכת מגיבה על ידי קריאה לאפליקציה כדי לקבל צללית של גרירה. לאחר מכן, המערכת מציגה את צל ההזזה במכשיר.
- לאחר מכן, המערכת שולחת אירוע גרירה עם סוג הפעולה
ACTION_DRAG_STARTED
למאזין של אירוע הגרירה של כל אובייקטי ה-View
בפריסה הנוכחית. כדי להמשיך לקבל אירועי גרירה – כולל אירוע השמטה אפשרי – ה-drag event listener צריך להחזיר את הערך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
, שמכיל סוג פעולה שמתאר את מה שקורה בתהליך הגרירה וההשלכה. בהתאם לסוג הפעולה, האובייקט יכול להכיל גם נתונים אחרים.
פונקציות 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 של רכיב ההקשבה לאירועי גרירה.
|
ACTION_DRAG_EXITED |
אחרי אירוע ACTION_DRAG_ENTERED ולפחות אירוע אחד מסוג ACTION_DRAG_LOCATION , צל ההזזה ינוע מחוץ לתיבת הגבול של View של רכיב ההקשבה לאירועי גרירה.
|
ACTION_DROP |
צללית ההזזה משתחררת מעל View של ה-event listener של ההזזה. סוג הפעולה הזה נשלח למאזין של אובייקט View רק אם המאזין מחזיר את הערך הבווליאני true בתגובה לאירוע הגרירה ACTION_DRAG_STARTED . סוג הפעולה הזה לא נשלח אם המשתמש משחרר את צללית ההזזה מעל View שה-listener שלו לא רשום, או אם המשתמש משחרר את צללית ההזזה מעל רכיב שאינו חלק מהפריסה הנוכחית.
אם המאזין מעבד את ההעברה בהצלחה, הוא מחזיר את הערך הבווליאני |
ACTION_DRAG_ENDED |
המערכת מסיימת את פעולת הגרירה והשליפה. סוג הפעולה הזה לא חייב להיות מלווה באירוע ACTION_DROP . אם המערכת שולחת ACTION_DROP , קבלת סוג הפעולה ACTION_DRAG_ENDED לא מעידה על כך שההשמטה הצליחה. כדי לקבל את הערך שמוחזר בתגובה ל-ACTION_DROP , המאזין צריך להפעיל את getResult() , כפי שמתואר בטבלה 2. אם לא נשלח אירוע 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, בהתאם לסוג התוצאה שלה.
צללית גרירה
במהלך פעולת גרירה ושחרור, המערכת מציגה תמונה שהמשתמש גורר. בתנועת נתונים, התמונה הזו מייצגת את הנתונים שנגררים. בפעולות אחרות, התמונה מייצגת היבט כלשהו של פעולת הגרירה.
התמונה נקראת צללית גרירה. יוצרים אותו באמצעות שיטות שמצהירים על אובייקט View.DragShadowBuilder
. מעבירים את ה-builder למערכת כשמתחילים פעולת גרירה ושחרור באמצעות startDragAndDrop()
. כחלק מהתגובה שלה להודעה startDragAndDrop()
, המערכת מפעילה את שיטות ה-callback שהגדרתם ב-View.DragShadowBuilder
כדי לקבל צללית של גרירה.
לכיתה View.DragShadowBuilder
יש שני קונסטרוקטורים:
View.DragShadowBuilder(View)
ה-constructor הזה מקבל כל אחד מהאובייקטים של
View
באפליקציה. ה-constructor שומר את האובייקטView
באובייקטView.DragShadowBuilder
, כדי שהפונקציות החוזרות (callbacks) יוכלו לגשת אליו כדי ליצור את צל הגרירה. התצוגה לא חייבת להיותView
שהמשתמש בוחר כדי להתחיל את פעולת הגרירה.אם משתמשים ב-constructor הזה, אין צורך להרחיב את
View.DragShadowBuilder
או לשנות את שיטותיו. כברירת מחדל, תקבלו צללית גרירה שמוצגת באותו מראה כמוView
שאתם מעבירים כארגומנטים, וממורכזת מתחת למיקום שבו המשתמש נגע במסך.View.DragShadowBuilder()
אם משתמשים ב-constructor הזה, לא יהיה אובייקט
View
באובייקטView.DragShadowBuilder
. השדה מוגדר ל-null
. צריך להרחיב אתView.DragShadowBuilder
ולשנות את השיטות שלו, אחרת תקבלו צללית גרירה בלתי נראית. המערכת לא תיצור שגיאה.
לכיתה 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 ושל קריאות חוזרות (callbacks)
View
מקבל אירועי גרירה באמצעות מאזין לאירועי גרירה שמטמיע את View.OnDragListener
או באמצעות שיטת ה-callback onDragEvent()
של התצוגה. כשהמערכת קוראת ל-method או ל-listener, היא מספקת ארגומנט DragEvent
.
ברוב המקרים, עדיף להשתמש בבורר במקום בשיטת ה-callback. בדרך כלל, כשמתכננים ממשקי משתמש לא יוצרים מחלקות משנה של View
, אבל השימוש ב-method callback מאלץ אתכם ליצור מחלקות משנה כדי לשנות את ברירת המחדל של ה-method. לעומת זאת, אפשר להטמיע סוג אחד של מאזין ולהשתמש בו עם כמה אובייקטים שונים של View
. אפשר גם להטמיע אותו כמחלקה אנונימית בקוד או כביטוי lambda. כדי להגדיר את המאזין לאובייקט View
, צריך להפעיל את השיטה setOnDragListener()
.
לחלופין, אפשר לשנות את ההטמעה שמוגדרת כברירת מחדל של onDragEvent()
בלי לשנות את השיטה. מגדירים את הערך OnReceiveContentListener
בתצוגה. פרטים נוספים זמינים במאמר setOnReceiveContentListener()
.
לאחר מכן, השיטה onDragEvent()
מבצעת את הפעולות הבאות כברירת מחדל:
- הפונקציה מחזירה את הערך true בתגובה לקריאה ל-
startDragAndDrop()
. performReceiveContent()
אם מושכים את הנתונים ומשחררים אותם בתצוגה. הנתונים מועברים לשיטה כאובייקטContentInfo
. השיטה מפעילה אתOnReceiveContentListener
.הפונקציה מחזירה את הערך true אם הנתונים שגוררים ומשחררים מושלכים לתצוגה ו-
OnReceiveContentListener
צורך חלק מהתוכן.
מגדירים את OnReceiveContentListener
כדי לטפל בנתונים באופן ספציפי לאפליקציה. לצורך תאימות לאחור עד לרמה 24 של API, משתמשים בגרסה של Jetpack ל-OnReceiveContentListener
.
אפשר להגדיר אוזן לאירועי גרירה ושיטת קריאה חוזרת (callback) לאובייקט View
. במקרה כזה, המערכת קודם קוראת לאוזן. המערכת לא קוראת לשיטת ה-callback אלא אם המאזין מחזיר את הערך false
.
השילוב של השיטה onDragEvent()
ו-View.OnDragListener
דומה לשילוב של onTouchEvent()
ו-View.OnTouchListener
שנעשה בו שימוש באירועי מגע.