टच और पॉइंटर मूवमेंट को ट्रैक करें

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

इस लेसन में बताया गया है कि टच इवेंट में हलचल को कैसे ट्रैक करें.

एक नया onTouchEvent() ट्रिगर करता है ACTION_MOVE इवेंट जब भी मौजूदा समय में टच किए जाने वाले संपर्क की स्थिति, दबाव या साइज़ में बदलाव हो. जैसे सामान्य जेस्चर का पता लगाएं सेक्शन में बताया गया है. इन इवेंट को इसमें रिकॉर्ड किया जाता है MotionEvent पैरामीटर onTouchEvent().

उंगली से टच करना हमेशा सटीक तरीके से नहीं हो पाता. इसलिए, ऐसा करना ज़रूरी नहीं है. टच इवेंट का पता लगाना, अक्सर सामान्य संपर्क के बजाय हलचल पर ज़्यादा आधारित होता है. गतिविधि के हिसाब से हाथ के जेस्चर (जैसे कि स्वाइप) और जेस्चर के बीच अंतर करने में ऐप्लिकेशन की मदद करने के लिए गैर-मूवमेंट जेस्चर (जैसे, एक बार टैप करना) का इस्तेमाल करते हैं, तो Android में ये बातें शामिल होती हैं: स्लोप को छुएं. टच स्लोप का मतलब पिक्सल में वह दूरी है जिसे उपयोगकर्ता टच कर सकता है हाथ के जेस्चर को हाथ के जेस्चर से पहले भटकना. ज़्यादा के लिए इस विषय के बारे में जानकारी पाने के लिए, टच इवेंट को मैनेज करने के बारे में जानने के लिए, ViewGroup.

हाथ के जेस्चर में गतिविधि को ट्रैक करने के कई तरीके हैं. ये तरीके आपके आवेदन की ज़रूरतों को पूरा करता है. ये उदाहरण हैं:

  • पॉइंटर के शुरू और खत्म होने की पोज़िशन, जैसे कि स्क्रीन पर मौजूद कर्सर को मूव करना ऑब्जेक्ट को पॉइंट A से पॉइंट B तक ले जाते हैं.
  • X और Y के आधार पर, पॉइंटर की दिशा निर्देशांक.
  • इतिहास पर टैप करें. जेस्चर के इतिहास का साइज़ जानने के लिए, MotionEvent तरीका getHistorySize(). इसके बाद, इन योद्धाओं की स्थिति, साइज़, समय, और दबाव का पता लगाया जा सकता है. मोशन इवेंट का इस्तेमाल करके ऐतिहासिक इवेंट getHistorical<Value> अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है तरीकों का इस्तेमाल करना होगा. उपयोगकर्ता की उंगली की पगडंडी को रेंडर करते समय इतिहास काम का होता है, जैसे जैसे कि टच ड्रॉइंग. ज़्यादा जानकारी के लिए, MotionEvent का रेफ़रंस देखें.
  • टचस्क्रीन पर चलने वाले पॉइंटर की वेलोसिटी.

यहां दिए गए मिलते-जुलते संसाधनों को देखें:

ट्रैक वेलोसिटी

आपके पास दूरी या दिशा के हिसाब से, हाथ के जेस्चर का इस्तेमाल करने का विकल्प है पॉइंटर यात्रा करता है. हालांकि, अक्सर ट्रैकिंग में संभावित तौर पर वेलोसिटी (वेग) तय होता है जेस्चर की विशेषताएँ या यह तय करने के लिए कि जेस्चर किया गया है या नहीं. बनाने में वेग की गणना आसान है, Android VelocityTracker क्लास. VelocityTracker की मदद से, टच इवेंट की रफ़्तार को ट्रैक किया जा सकता है. यह काम का है जिनमें वेलोसिटी, जेस्चर के मापदंड का हिस्सा होती है. जैसे फ़्लिंग करें.

यहां एक उदाहरण दिया गया है, जिसमें बताया गया है कि VelocityTracker एपीआई:

Kotlin

private const val DEBUG_TAG = "Velocity"

class MainActivity : Activity() {
    private var mVelocityTracker: VelocityTracker? = null

    override fun onTouchEvent(event: MotionEvent): Boolean {

        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                // Reset the velocity tracker back to its initial state.
                mVelocityTracker?.clear()
                // If necessary, retrieve a new VelocityTracker object to watch
                // the velocity of a motion.
                mVelocityTracker = mVelocityTracker ?: VelocityTracker.obtain()
                // Add a user's movement to the tracker.
                mVelocityTracker?.addMovement(event)
            }
            MotionEvent.ACTION_MOVE -> {
                mVelocityTracker?.apply {
                    val pointerId: Int = event.getPointerId(event.actionIndex)
                    addMovement(event)
                    // When you want to determine the velocity, call
                    // computeCurrentVelocity(). Then, call getXVelocity() and
                    // getYVelocity() to retrieve the velocity for each pointer
                    // ID.
                    computeCurrentVelocity(1000)
                    // Log velocity of pixels per second. It's best practice to
                    // use VelocityTrackerCompat where possible.
                    Log.d("", "X velocity: ${getXVelocity(pointerId)}")
                    Log.d("", "Y velocity: ${getYVelocity(pointerId)}")
                }
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                // Return a VelocityTracker object back to be re-used by others.
                mVelocityTracker?.recycle()
                mVelocityTracker = null
            }
        }
        return true
    }
}

Java

public class MainActivity extends Activity {
    private static final String DEBUG_TAG = "Velocity";
        ...
    private VelocityTracker mVelocityTracker = null;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int index = event.getActionIndex();
        int action = event.getActionMasked();
        int pointerId = event.getPointerId(index);

        switch(action) {
            case MotionEvent.ACTION_DOWN:
                if(mVelocityTracker == null) {
                    // Retrieve a new VelocityTracker object to watch the
                    // velocity of a motion.
                    mVelocityTracker = VelocityTracker.obtain();
                }
                else {
                    // Reset the velocity tracker back to its initial state.
                    mVelocityTracker.clear();
                }
                // Add a user's movement to the tracker.
                mVelocityTracker.addMovement(event);
                break;
            case MotionEvent.ACTION_MOVE:
                mVelocityTracker.addMovement(event);
                // When you want to determine the velocity, call
                // computeCurrentVelocity(). Then call getXVelocity() and
                // getYVelocity() to retrieve the velocity for each pointer ID.
                mVelocityTracker.computeCurrentVelocity(1000);
                // Log velocity of pixels per second. It's best practice to use
                // VelocityTrackerCompat where possible.
                Log.d("", "X velocity: " + mVelocityTracker.getXVelocity(pointerId));
                Log.d("", "Y velocity: " + mVelocityTracker.getYVelocity(pointerId));
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                // Return a VelocityTracker object back to be re-used by others.
                mVelocityTracker.recycle();
                break;
        }
        return true;
    }
}

पॉइंटर कैप्चर का इस्तेमाल करना

गेम और रिमोट डेस्कटॉप और वर्चुअलाइज़ेशन क्लाइंट जैसे कुछ ऐप्लिकेशन को इससे फ़ायदा मिलता है इससे उपयोगकर्ता को माउस पॉइंटर पर कंट्रोल करने से रोका जा सकता है. पॉइंटर कैप्चर एक सुविधा है Android 8.0 (एपीआई लेवल 26) और उसके बाद के वर्शन में उपलब्ध है जो इससे आपके ऐप्लिकेशन में, फ़ोकस वाले व्यू पर सभी माउस इवेंट को डिलीवर किया जा सकता है.

पॉइंटर कैप्चर करने का अनुरोध करें

आपके ऐप्लिकेशन का कोई व्यू, पॉइंटर कैप्चर करने का अनुरोध सिर्फ़ तब कर सकता है, जब व्यू हैरारकी उसमें फ़ोकस है. इस वजह से, उपयोगकर्ता की कार्रवाई को देखना, जैसे कि onClick() इवेंट या onWindowFocusChanged() आपकी गतिविधि का इवेंट हैंडलर.

पॉइंटर कैप्चर का अनुरोध करने के लिए, requestPointerCapture() तरीका भी चुना जा सकता है. यहां दिए गए कोड के उदाहरण में, पॉइंटर का अनुरोध करने का तरीका बताया गया है जब उपयोगकर्ता किसी व्यू पर क्लिक करता है, तो उसे कैप्चर करता है:

Kotlin

fun onClick(view: View) {
    view.requestPointerCapture()
}

Java

@Override
public void onClick(View view) {
    view.requestPointerCapture();
}

पॉइंटर कैप्चर करने का अनुरोध पूरा होने पर, Android कॉल onPointerCaptureChange(true). सिस्टम, आपके ऐप्लिकेशन में फ़ोकस किए गए व्यू पर तब तक माउस इवेंट डिलीवर करता है, जब तक यह उसी व्यू हैरारकी में है जिसमें कैप्चर का अनुरोध करने वाला व्यू है. किसी और तरीके से कैप्चर किए जाने तक, ऐप्लिकेशन को माउस से जुड़े इवेंट मिलना बंद हो जाते हैं. जैसे, ACTION_OUTSIDE इवेंट. Android, माउस के अलावा अन्य सोर्स से पॉइंटर इवेंट इस तरह डिलीवर करता है: सामान्य लेकिन माउस पॉइंटर अब दिखाई नहीं देता.

कैप्चर किए गए पॉइंटर इवेंट मैनेज करना

जब कोई व्यू पॉइंटर कैप्चर हासिल कर लेता है, तब Android माउस इवेंट. फ़ोकस किया गया व्यू इनमें से कोई एक कार्रवाई करके, इवेंट मैनेज कर सकता है ये काम पूरे करें:

नीचे दिया गया कोड उदाहरण, कन्वर्ज़न ट्रैकिंग को लागू करने का तरीका बताता है onCapturedPointerEvent(MotionEvent):

Kotlin

override fun onCapturedPointerEvent(motionEvent: MotionEvent): Boolean {
    // Get the coordinates required by your app.
    val verticalOffset: Float = motionEvent.y
    // Use the coordinates to update your view and return true if the event is
    // successfully processed.
    return true
}

Java

@Override
public boolean onCapturedPointerEvent(MotionEvent motionEvent) {
  // Get the coordinates required by your app.
  float verticalOffset = motionEvent.getY();
  // Use the coordinates to update your view and return true if the event is
  // successfully processed.
  return true;
}

नीचे दिए गए उदाहरण में, OnCapturedPointerListener:

Kotlin

myView.setOnCapturedPointerListener { view, motionEvent ->
    // Get the coordinates required by your app.
    val horizontalOffset: Float = motionEvent.x
    // Use the coordinates to update your view and return true if the event is
    // successfully processed.
    true
}

Java

myView.setOnCapturedPointerListener(new View.OnCapturedPointerListener() {
  @Override
  public boolean onCapturedPointer (View view, MotionEvent motionEvent) {
    // Get the coordinates required by your app.
    float horizontalOffset = motionEvent.getX();
    // Use the coordinates to update your view and return true if the event is
    // successfully processed.
    return true;
  }
});

चाहे आप कस्टम व्यू का इस्तेमाल करें या लिसनर को रजिस्टर करें, आपके व्यू को पॉइंटर कोऑर्डिनेट के साथ MotionEvent, जो X जैसी रिलेटिव मूवमेंट को दिखाते हैं या Y डेल्टा, किसी ट्रैकबॉल डिवाइस से डिलीवर किए गए निर्देशांकों की तरह. आप निर्देशांकों को getX() और getY().

पॉइंटर कैप्चर करें

आपके ऐप्लिकेशन का व्यू, कॉल करके पॉइंटर कैप्चर को रिलीज़ कर सकता है releasePointerCapture() जैसा कि नीचे दिए गए कोड उदाहरण में दिखाया गया है:

Kotlin

override fun onClick(view: View) {
    view.releasePointerCapture()
}

Java

@Override
public void onClick(View view) {
    view.releasePointerCapture();
}

सिस्टम, कैप्चर किए गए कैप्चर को ज़रूरत के हिसाब से व्यू से बाहर ले जा सकता है releasePointerCapture() को कॉल किया जा रहा है. आम तौर पर, ऐसा व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) की वजह से होता है जिसमें कैप्चर करने का अनुरोध करने वाला व्यू शामिल है, फ़ोकस खो जाता है.