תנועה לכמה נקודות מגע מתרחשת כשכמה מצביעים (אצבעות) מקישים על המסך כמעט באותה עת. במסמך הזה מוסבר איך לזהות תנועות שכוללות כמה מצביעים.
מעקב אחרי כמה מצביעים
כשכמה מצביעים מקישים על המסך בו-זמנית, המערכת יוצרת אירועי המגע הבאים:
ACTION_DOWN
: נשלחת כשהסמן הראשון יקיש על המסך. הפעולה הזו תתחיל את התנועה. נתוני מצביע עבור מצביע זה תמיד נמצאים באינדקס0
ב-MotionEvent
.ACTION_POINTER_DOWN
: נשלחת כשסמנים נוספים נכנסים למסך אחרי הראשון. אפשר לקבל האינדקס של הסמן שירד באמצעותgetActionIndex()
ACTION_MOVE
: נשלחים כששינוי מתרחש בתנועה, שכוללת כל מספר את המצביעים.ACTION_POINTER_UP
: נשלח כאשר מצביע שאינו עיקרי עולה. אפשר לקבל את האינדקס של מצביע בדיוק עלה באמצעותgetActionIndex()
.ACTION_UP
: נשלח כשהסמן האחרון יוצא מהמסך.ACTION_CANCEL
: מציין שהתנועה כולה, כולל כל המצביעים, בוטלה.
תנועות של התחלה וסיום
תנועה היא סדרה של אירועים המתחילים ב-ACTION_DOWN
אירוע ומסתיים בספרות ACTION_UP
או
אירוע ACTION_CANCEL
. יש תנועה פעילה אחת בכל פעם.
פעולות למטה, העברה, העלאה וביטול חלות על כל התנועה. לדוגמה,
אירוע עם ACTION_MOVE
יכול לציין תנועה בכל הסמן
למטה באותו רגע.
מעקב אחר המצביעים
שימוש באינדקס ובמזהה של הסמן כדי לעקוב אחרי כל מצביע בנפרד
מיקומים בטווח MotionEvent
.
- אינדקס: מצביע של
MotionEvent
לחנות מידע במערך. האינדקס של מצביע הוא המיקום שלו בתוך מערך. ברוב השיטות שלMotionEvent
, אינדקס המצביע מוגדר כ פרמטר ולא מזהה מצביע. - מזהה: לכל מצביע יש גם מיפוי מזהה שנשאר קבוע בכל אירועי המגע כדי לאפשר מעקב אחר מצביע ספציפי לכל התנועה.
מצביעים בודדים מופיעים בתוך אירוע תנועה בסדר לא מוגדר. כך,
האינדקס של מצביע יכול להשתנות מאירוע אחד לאירוע הבא, אבל מזהה המצביע
מובטח שיישאר קבוע כל עוד הוא נשאר
פעיל. משתמשים ב
getPointerId()
לקבלת מזהה של מצביע
אירועי תנועה בתנועה. לאחר מכן, לאירועי תנועה עוקבים, משתמשים
findPointerIndex()
לקבלת אינדקס מצביע עבור מזהה מצביע נתון באירוע התנועה הזה.
לדוגמה:
Kotlin
private var mActivePointerId: Int = 0 override fun onTouchEvent(event: MotionEvent): Boolean { ... // Get the pointer ID. mActivePointerId = event.getPointerId(0) // ... Many touch events later... // Use the pointer ID to find the index of the active pointer // and fetch its position. val (x: Float, y: Float) = event.findPointerIndex(mActivePointerId).let { pointerIndex -> // Get the pointer's current position. event.getX(pointerIndex) to event.getY(pointerIndex) } ... }
Java
private int mActivePointerId; public boolean onTouchEvent(MotionEvent event) { ... // Get the pointer ID. mActivePointerId = event.getPointerId(0); // ... Many touch events later... // Use the pointer ID to find the index of the active pointer // and fetch its position. int pointerIndex = event.findPointerIndex(mActivePointerId); // Get the pointer's current position. float x = event.getX(pointerIndex); float y = event.getY(pointerIndex); ... }
כדי לתמוך בכמה מצביעים עם מגע, אפשר לשמור במטמון את כל המצביעים הפעילים באמצעות
את התעודה המזהה בACTION_POINTER_DOWN
וגם
זמן האירוע: ACTION_DOWN
. הסרת המצביעים מהמטמון ב-
את אירועי ACTION_POINTER_UP
ו-ACTION_UP
שלהם. ייתכן ש
מזהים שנשמרו במטמון שימושיים לטיפול באירועי פעולות אחרים בצורה נכונה. עבור
לדוגמה, כשמעבדים אירוע ACTION_MOVE
, מחפשים את האינדקס של
כל מזהה של מצביע פעיל שנשמר במטמון, מאחזר את הקואורדינטות של המצביע באמצעות
getX()
וגם
getY()
שלנו, השוו בין הקואורדינטות האלה עם הקואורדינטות השמורות
לגלות אילו מצביעים עברו.
משתמשים בפונקציה getActionIndex()
עם
אירועים ACTION_POINTER_UP
ו-ACTION_POINTER_DOWN
בלבד. לא להשתמש בפונקציה הזו עם אירועי ACTION_MOVE
, כי
הפונקציה תמיד מחזירה 0
.
אחזור MotionEvent
פעולות
משתמשים ב
getActionMasked()
method או את גרסת התאימות
MotionEventCompat.getActionMasked()
כדי לאחזר את הפעולה של MotionEvent
. בניגוד לקודמים
getAction()
השיטה getActionMasked()
תוכננה לפעול עם
את המצביעים. היא מחזירה את הפעולה ללא האינדקסים של המצביעים. עבור פעולות עם רכיב
אינדקס מצביע חוקי, צריך להשתמש ב-getActionIndex()
כדי להחזיר את האינדקס של
את המצביעים המשויכים לפעולה, כפי שמוצג בקטע הקוד הבא:
Kotlin
val (xPos: Int, yPos: Int) = MotionEventCompat.getActionMasked(event).let { action -> Log.d(DEBUG_TAG, "The action is ${actionToString(action)}") // Get the index of the pointer associated with the action. MotionEventCompat.getActionIndex(event).let { index -> // The coordinates of the current screen contact, relative to // the responding View or Activity. MotionEventCompat.getX(event, index).toInt() to MotionEventCompat.getY(event, index).toInt() } } if (event.pointerCount > 1) { Log.d(DEBUG_TAG, "Multitouch event") } else { // Single touch event. Log.d(DEBUG_TAG, "Single touch event") } ... // Given an action int, returns a string description. fun actionToString(action: Int): String { return when (action) { MotionEvent.ACTION_DOWN -> "Down" MotionEvent.ACTION_MOVE -> "Move" MotionEvent.ACTION_POINTER_DOWN -> "Pointer Down" MotionEvent.ACTION_UP -> "Up" MotionEvent.ACTION_POINTER_UP -> "Pointer Up" MotionEvent.ACTION_OUTSIDE -> "Outside" MotionEvent.ACTION_CANCEL -> "Cancel" else -> "" } }
Java
int action = MotionEventCompat.getActionMasked(event); // Get the index of the pointer associated with the action. int index = MotionEventCompat.getActionIndex(event); int xPos = -1; int yPos = -1; Log.d(DEBUG_TAG,"The action is " + actionToString(action)); if (event.getPointerCount() > 1) { Log.d(DEBUG_TAG,"Multitouch event"); // The coordinates of the current screen contact, relative to // the responding View or Activity. xPos = (int)MotionEventCompat.getX(event, index); yPos = (int)MotionEventCompat.getY(event, index); } else { // Single touch event. Log.d(DEBUG_TAG,"Single touch event"); xPos = (int)MotionEventCompat.getX(event, index); yPos = (int)MotionEventCompat.getY(event, index); } ... // Given an action int, returns a string description public static String actionToString(int action) { switch (action) { case MotionEvent.ACTION_DOWN: return "Down"; case MotionEvent.ACTION_MOVE: return "Move"; case MotionEvent.ACTION_POINTER_DOWN: return "Pointer Down"; case MotionEvent.ACTION_UP: return "Up"; case MotionEvent.ACTION_POINTER_UP: return "Pointer Up"; case MotionEvent.ACTION_OUTSIDE: return "Outside"; case MotionEvent.ACTION_CANCEL: return "Cancel"; } return ""; }
מקורות מידע נוספים
מידע נוסף בנוגע לאירועי קלט מופיע במאמרים הבאים: הפניות: