الإيماءة التي تعمل باللمس المتعدّد هي عندما تنقر مؤشرات متعددة (أصابع) على الشاشة في الوقت نفسه. يوضّح هذا المستند كيفية رصد الإيماءات التي تتضمّن مؤشرات متعددة.
تتبُّع مؤشرات متعددة
عندما تنقر مؤشرات متعددة على الشاشة في الوقت نفسه، ينشئ النظام أحداث اللمس التالية:
ACTION_DOWN
: يتم إرسالها عندما ينقر المؤشر الأول على الشاشة. يؤدي ذلك إلى بدء الإجراء. إنّ بيانات المؤشر لهذا المؤشر تكون دائمًا في الفهرس0
فيMotionEvent
.ACTION_POINTER_DOWN
: يتم إرسالها عندما تدخل مؤشرات إضافية إلى الشاشة بعد المؤشر الأول. يمكنك الحصول على فهرس المؤشر الذي انخفض للتو باستخدامgetActionIndex()
.-
ACTION_MOVE
: يتم إرسالها عند حدوث تغيير في إيماءة، يشمل أي عدد من المؤشرات. -
ACTION_POINTER_UP
: يتم إرسال هذا الحدث عندما يرتفع مؤشر غير أساسي. يمكنك الحصول على فهرس المؤشر الذي تمّت ترقيته للتو باستخدامgetActionIndex()
. ACTION_UP
: يتم إرسالها عندما يغادر المؤشر الأخير الشاشة.-
ACTION_CANCEL
: يشير إلى إلغاء الإيماءة بالكامل، بما في ذلك جميع المؤشرات.
إيماءات البدء والانتهاء
الإيماءة هي سلسلة من الأحداث تبدأ بحدث ACTION_DOWN
وتنتهي إما بحدث ACTION_UP
أو
ACTION_CANCEL
. تكون هناك إيماءة نشطة واحدة في كل مرة. تنطبق
الإجراءات DOWN وMOVE وUP و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 ""; }
مصادر إضافية
لمزيد من المعلومات المتعلّقة بأحداث الإدخال، اطّلِع على المراجع التالية:
- نظرة عامة على أحداث الإدخال
- نظرة عامة على أدوات الاستشعار
- جعل عرض مخصّص تفاعليًا
- السحب والتكبير/التصغير