मल्टी-टच जेस्चर हैंडल करने की सुविधा

'लिखें' सुविधा आज़माएं
Android के लिए, Jetpack Compose को यूज़र इंटरफ़ेस (यूआई) टूलकिट के तौर पर सुझाया जाता है. Compose में टच और इनपुट इस्तेमाल करने का तरीका जानें.

मल्टी-टच जेस्चर तब होता है, जब एक से ज़्यादा पॉइंटर (उंगलियां) एक ही समय पर स्क्रीन पर टैप करते हैं. इस दस्तावेज़ में, एक से ज़्यादा पॉइंटर वाले जेस्चर का पता लगाने का तरीका बताया गया है.

एक से ज़्यादा पॉइंटर ट्रैक करना

जब एक साथ कई पॉइंटर स्क्रीन पर टैप करते हैं, तो सिस्टम ये टच इवेंट जनरेट करता है:

  • ACTION_DOWN: यह तब भेजा जाता है, जब पहला पॉइंटर स्क्रीन पर टैप करता है. इससे जेस्चर शुरू हो जाता है. इस पॉइंटर का पॉइंटर डेटा, MotionEvent में हमेशा इंडेक्स 0 पर होता है.
  • 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 कार्रवाइयां वापस पाना

MotionEvent की कार्रवाई को वापस पाने के लिए, getActionMasked() के तरीके या साथ काम करने वाले वर्शन MotionEventCompat.getActionMasked() का इस्तेमाल करें. 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 "";
}
पहली इमेज. मल्टी-टच ड्रॉइंग पैटर्न.

अन्य संसाधन

इनपुट इवेंट के बारे में ज़्यादा जानने के लिए, ये रेफ़रंस देखें: