التعامل مع إيماءات اللمس المتعدد

تجربة طريقة ComposeAllowed
Jetpack Compose هي مجموعة أدوات واجهة المستخدم التي ننصح بها لنظام التشغيل Android. تعرَّف على كيفية استخدام اللمس والإدخال في ميزة "إنشاء".

تحدث إيماءة اللمس المتعدد عندما تنقر عدة مؤشرات (أصابع) على الشاشة في نفس الوقت. يصف هذا المستند كيفية اكتشاف الإيماءات التي تتضمن مؤشرات متعددة.

تتبُّع مؤشرات متعددة

عندما تنقر عدة مؤشرات على الشاشة في الوقت نفسه، ينشئ النظام أحداث اللمس التالية:

  • 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 "";
}
الشكل 1. رسم متعدد اللمس الأنماط.

مصادر إضافية

لمزيد من المعلومات حول أحداث الإدخال، يُرجى الاطّلاع على ما يلي: المراجع: