يتم تسجيل إيماءة اللمس المتعدد عند نقر عدة مؤشرات (أصابع) على الشاشة في الوقت نفسه. يشرح هذا المستند كيفية اكتشاف الإيماءات التي تتضمّن مؤشرات متعددة.
تتبُّع عدة مؤشرات
عندما تنقر عدة مؤشرات على الشاشة في الوقت نفسه، يُنشئ النظام أحداث اللمس التالية:
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()
أو إصدار التوافق
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 ""; }
مراجع إضافية
لمزيد من المعلومات حول أحداث الإدخال، اطّلِع على المراجع التالية: