इनपुट इवेंट की खास जानकारी

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

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

लेआउट कंपोज़ करने के लिए, View की अलग-अलग क्लास का इस्तेमाल किया जाता है. इनमें आपको कई ऐसे सार्वजनिक कॉलबैक तरीके दिख सकते हैं जो यूज़र इंटरफ़ेस (यूआई) इवेंट के लिए काम के हो सकते हैं. जब उस ऑब्जेक्ट पर कोई कार्रवाई होती है, तो Android फ़्रेमवर्क इन तरीकों को कॉल करता है. उदाहरण के लिए, जब किसी View (जैसे कि बटन) को छुआ जाता है, तो उस ऑब्जेक्ट पर onTouchEvent() तरीका कॉल किया जाता है. हालांकि, इसे इंटरसेप्ट करने के लिए, आपको क्लास को बढ़ाना होगा और तरीके को ओवरराइड करना होगा. हालांकि, इस तरह के इवेंट को मैनेज करने के लिए, हर View ऑब्जेक्ट को बढ़ाना सही नहीं होगा. इसलिए, View क्लास में नेस्ट किए गए इंटरफ़ेस का कलेक्शन भी होता है. इसमें कॉलबैक होते हैं जिन्हें आसानी से तय किया जा सकता है. इन इंटरफ़ेस को, इवेंट लिसनर कहा जाता है. इनकी मदद से, यूज़र इंटरफ़ेस (यूआई) के साथ उपयोगकर्ता के इंटरैक्शन को कैप्चर किया जा सकता है.

आम तौर पर, उपयोगकर्ता के इंटरैक्शन को सुनने के लिए इवेंट लिसनर का इस्तेमाल किया जाता है. हालांकि, ऐसा भी हो सकता है कि आपको कस्टम कॉम्पोनेंट बनाने के लिए, View क्लास को बढ़ाना पड़े. उदाहरण के लिए, हो सकता है कि आपको Button क्लास को बढ़ाकर, कुछ और बेहतर बनाना हो. ऐसे में, क्लास इवेंट हैंडलर का इस्तेमाल करके, अपनी क्लास के लिए डिफ़ॉल्ट इवेंट के व्यवहार तय किए जा सकते हैं.

इवेंट लिसनर

इवेंट लिसनर, View क्लास में मौजूद एक इंटरफ़ेस है. इसमें एक कॉलबैक तरीका होता है. जब यूज़र इंटरफ़ेस (यूआई) में मौजूद किसी आइटम के साथ उपयोगकर्ता के इंटरैक्शन से, उस View को ट्रिगर किया जाता है जिसके लिए लिसनर रजिस्टर किया गया है, तो Android फ़्रेमवर्क इन तरीकों को कॉल करेगा.

इवेंट लिसनर इंटरफ़ेस में, ये कॉलबैक तरीके शामिल हैं:

onClick()
View.OnClickListener से. जब उपयोगकर्ता, आइटम को छूता है (टच मोड में होने पर) या नेविगेशन-की या ट्रैकबॉल की मदद से आइटम पर फ़ोकस करता है और "एंटर" कुंजी दबाता है या ट्रैकबॉल को दबाता है, तो इसे कॉल किया जाता है.
onLongClick()
View.OnLongClickListener से. जब उपयोगकर्ता, आइटम को छूकर दबाए रखता है (टच मोड में होने पर) या नेविगेशन-की या ट्रैकबॉल की मदद से आइटम पर फ़ोकस करता है और "एंटर" कुंजी को दबाकर रखता है या ट्रैकबॉल को दबाकर रखता है (एक सेकंड के लिए), तो इसे कॉल किया जाता है.
onFocusChange()
View.OnFocusChangeListener से. जब उपयोगकर्ता, नेविगेशन-की या ट्रैकबॉल का इस्तेमाल करके, आइटम पर नेविगेट करता है या उससे दूर जाता है, तो इसे कॉल किया जाता है.
onKey()
View.OnKeyListener से. जब उपयोगकर्ता, आइटम पर फ़ोकस करता है और डिवाइस पर मौजूद हार्डवेयर की को दबाता है या छोड़ता है, तो इसे कॉल किया जाता है.
onTouch()
View.OnTouchListener से. जब उपयोगकर्ता, टच इवेंट के तौर पर कोई कार्रवाई करता है, तो इसे कॉल किया जाता है. इसमें स्क्रीन पर आइटम की सीमाओं के अंदर, दबाना, छोड़ना या कोई भी मूवमेंट जेस्चर शामिल है.
onCreateContextMenu()
View.OnCreateContextMenuListener से. जब कॉन्टेक्स्ट मेन्यू बनाया जा रहा होता है (लगातार "लॉन्ग क्लिक" करने पर), तो इसे कॉल किया जाता है. कॉन्टेक्स्ट मेन्यू के बारे में जानने के लिए, डेवलपर गाइड में मेन्यू सेक्शन देखें.

ये तरीके, अपने-अपने इंटरफ़ेस के एकमात्र सदस्य हैं. इनमें से किसी एक तरीके को तय करने और अपने इवेंट को मैनेज करने के लिए, अपनी गतिविधि में नेस्ट किए गए इंटरफ़ेस को लागू करें या इसे एनॉनिमस क्लास के तौर पर तय करें. इसके बाद, अपने लागू करने का इंस्टेंस, संबंधित View.set...Listener() तरीके को पास करें. उदाहरण के लिए, setOnClickListener() को कॉल करें और इसे OnClickListener के अपने लागू करने का तरीका पास करें.

नीचे दिए गए उदाहरण में, बटन के लिए ऑन-क्लिक लिसनर रजिस्टर करने का तरीका बताया गया है.

Kotlin

protected void onCreate(savedValues: Bundle) {
    ...
    val button: Button = findViewById(R.id.corky)
    // Register the onClick listener with the implementation above
    button.setOnClickListener { view ->
        // do something when the button is clicked
    }
    ...
}

Java

// Create an anonymous implementation of OnClickListener
private OnClickListener corkyListener = new OnClickListener() {
    public void onClick(View v) {
      // do something when the button is clicked
    }
};

protected void onCreate(Bundle savedValues) {
    ...
    // Capture our button from layout
    Button button = (Button)findViewById(R.id.corky);
    // Register the onClick listener with the implementation above
    button.setOnClickListener(corkyListener);
    ...
}

OnClickListener को अपनी गतिविधि के हिस्से के तौर पर लागू करना भी ज़्यादा सुविधाजनक हो सकता है. इससे, क्लास लोड और ऑब्जेक्ट के लिए जगह की ज़रूरत नहीं पड़ेगी. उदाहरण के लिए:

Kotlin

class ExampleActivity : Activity(), OnClickListener {
  
    protected fun onCreate(savedValues: Bundle) {
        val button: Button = findViewById(R.id.corky)
        button.setOnClickListener(this)
    }

    // Implement the OnClickListener callback
    fun onClick(v: View) {
        // do something when the button is clicked
    }
}

Java

public class ExampleActivity extends Activity implements OnClickListener {
    protected void onCreate(Bundle savedValues) {
        ...
        Button button = (Button)findViewById(R.id.corky);
        button.setOnClickListener(this);
    }

    // Implement the OnClickListener callback
    public void onClick(View v) {
      // do something when the button is clicked
    }
    ...
}

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

  • onLongClick() - यह बूलियन वैल्यू दिखाता है, ताकि यह पता चल सके कि आपने इवेंट का इस्तेमाल किया है या नहीं. साथ ही, यह भी पता चलता है कि इसे आगे नहीं ले जाना चाहिए. इसका मतलब है कि अगर आपने इवेंट को मैनेज किया है और इसे यहीं रोकना है, तो सही वैल्यू दिखाएं. अगर आपने इसे मैनेज नहीं किया है और/या इवेंट को किसी अन्य ऑन-क्लिक लिसनर पर जारी रखना है, तो गलत वैल्यू दिखाएं.
  • onKey() - यह बूलियन वैल्यू दिखाता है, ताकि यह पता चल सके कि आपने इवेंट का इस्तेमाल किया है या नहीं. साथ ही, यह भी पता चलता है कि इसे आगे नहीं ले जाना चाहिए. इसका मतलब है कि अगर आपने इवेंट को मैनेज किया है और इसे यहीं रोकना है, तो सही वैल्यू दिखाएं. अगर आपने इसे मैनेज नहीं किया है और/या इवेंट को किसी अन्य ऑन-की लिसनर पर जारी रखना है, तो गलत वैल्यू दिखाएं.
  • onTouch() - यह बूलियन वैल्यू दिखाता है, ताकि यह पता चल सके कि आपका लिसनर इस इवेंट का इस्तेमाल करता है या नहीं. अहम बात यह है कि यह इवेंट एक के बाद एक कई कार्रवाइयां कर सकता है. इसलिए, अगर डाउन ऐक्शन इवेंट मिलने पर, गलत वैल्यू दिखाई जाती है, तो इसका मतलब है कि आपने इवेंट का इस्तेमाल नहीं किया है. साथ ही, आपको इस इवेंट से जुड़ी अन्य कार्रवाइयों में भी दिलचस्पी नहीं है. इसलिए, आपको इवेंट में मौजूद अन्य कार्रवाइयों के लिए कॉल नहीं किया जाएगा. जैसे, फ़िंगर जेस्चर या अप ऐक्शन इवेंट.

ध्यान रखें कि हार्डवेयर की इवेंट हमेशा उस View को डिलीवर किए जाते हैं जिस पर फ़िलहाल फ़ोकस है. इन्हें View के क्रम के सबसे ऊपर से भेजा जाता है. इसके बाद, ये तब तक नीचे भेजे जाते हैं, जब तक ये सही जगह पर नहीं पहुंच जाते. अगर फ़िलहाल आपके View (या आपके View के किसी चाइल्ड) पर फ़ोकस है, तो dispatchKeyEvent() तरीके से इवेंट को भेजा जा सकता है. View के ज़रिए की इवेंट कैप्चर करने के अलावा, अपनी गतिविधि में सभी इवेंट भी पाए जा सकते हैं onKeyDown() और onKeyUp().

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

ध्यान दें: Android, सबसे पहले इवेंट हैंडलर को कॉल करेगा. इसके बाद, क्लास की परिभाषा से जुड़े डिफ़ॉल्ट हैंडलर को कॉल करेगा. ऐसे में, इन इवेंट लिसनर से सही वैल्यू दिखाने पर, इवेंट को अन्य इवेंट लिसनर पर नहीं भेजा जाएगा. साथ ही, View में मौजूद डिफ़ॉल्ट इवेंट हैंडलर को कॉलबैक भी ब्लॉक कर दिया जाएगा. इसलिए, सही वैल्यू दिखाने से पहले पक्का करें कि आपको इवेंट को खत्म करना है.

इवेंट हैंडलर

अगर View से कोई कस्टम कॉम्पोनेंट बनाया जा रहा है, तो डिफ़ॉल्ट इवेंट हैंडलर के तौर पर इस्तेमाल किए जाने वाले कई कॉलबैक तरीके तय किए जा सकते हैं. कस्टम व्यू कॉम्पोनेंट के बारे में दस्तावेज़ में, इवेंट हैंडलिंग के लिए इस्तेमाल किए जाने वाले कुछ सामान्य कॉलबैक के बारे में बताया गया है. इनमें ये शामिल हैं:

  • onKeyDown(int, KeyEvent) - नया की इवेंट होने पर कॉल किया जाता है.
  • onKeyUp(int, KeyEvent) - की अप इवेंट होने पर कॉल किया जाता है.
  • onTrackballEvent(MotionEvent) - ट्रैकबॉल मोशन इवेंट होने पर कॉल किया जाता है.
  • onTouchEvent(MotionEvent) - टच स्क्रीन मोशन इवेंट होने पर कॉल किया जाता है.
  • onFocusChanged(boolean, int, Rect) - व्यू को फ़ोकस मिलने या फ़ोकस खोने पर कॉल किया जाता है.

कुछ अन्य तरीके भी हैं जिनके बारे में आपको पता होना चाहिए. ये तरीके, View क्लास का हिस्सा नहीं हैं, लेकिन ये सीधे तौर पर इस बात पर असर डाल सकते हैं कि इवेंट को कैसे मैनेज किया जाता है. इसलिए, लेआउट में ज़्यादा जटिल इवेंट मैनेज करते समय, इन अन्य तरीकों पर विचार करें:

स्पर्श मोड

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

टच की सुविधा वाले डिवाइस के लिए, जब उपयोगकर्ता स्क्रीन को छूता है, तो डिवाइस टच मोड में चला जाता है. इसके बाद, सिर्फ़ वे View फ़ोकस किए जा सकेंगे जिनके लिए isFocusableInTouchMode() की वैल्यू सही है. जैसे, टेक्स्ट में बदलाव करने वाले विजेट. टच किए जा सकने वाले अन्य View, जैसे कि बटन, छूने पर फ़ोकस नहीं करेंगे. दबाने पर, वे सिर्फ़ अपने ऑन-क्लिक लिसनर को ट्रिगर करेंगे.

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

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

फ़ोकस मैनेज करना

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

Android 9 (एपीआई लेवल 28) या इसके बाद के वर्शन पर चलने वाले डिवाइसों पर, गतिविधियां शुरुआती फ़ोकस असाइन नहीं करती हैं. इसके बजाय, अगर आपको शुरुआती फ़ोकस का अनुरोध करना है, तो आपको साफ़ तौर पर ऐसा करना होगा.

फ़ोकस का मूवमेंट, किसी दी गई दिशा में सबसे नज़दीकी पड़ोसी को ढूंढने वाले एल्गोरिदम पर आधारित होता है. हालांकि, कुछ मामलों में, डिफ़ॉल्ट एल्गोरिदम, डेवलपर के हिसाब से काम नहीं कर सकता. ऐसे में, लेआउट फ़ाइल में मौजूद इन एक्सएमएल एट्रिब्यूट की मदद से, साफ़ तौर पर ओवरराइड किया जा सकता है: nextFocusDown, nextFocusLeft, nextFocusRight, और nextFocusUp. इनमें से कोई एक एट्रिब्यूट, उस View में जोड़ें जिससे फ़ोकस हट रहा है. एट्रिब्यूट की वैल्यू को, उस View की आईडी के तौर पर तय करें जिस पर फ़ोकस किया जाना चाहिए. उदाहरण के लिए:

<LinearLayout
    android:orientation="vertical"
    ... >
  <Button android:id="@+id/top"
          android:nextFocusUp="@+id/bottom"
          ... />
  <Button android:id="@+id/bottom"
          android:nextFocusDown="@+id/top"
          ... />
</LinearLayout>

आम तौर पर, इस वर्टिकल लेआउट में, पहले बटन से ऊपर की ओर नेविगेट करने पर, कहीं नहीं जाया जा सकेगा. साथ ही, दूसरे बटन से नीचे की ओर नेविगेट करने पर भी ऐसा ही होगा. अब सबसे ऊपर मौजूद बटन ने सबसे नीचे मौजूद बटन को nextFocusUp के तौर पर तय किया है (और इसके उलट भी). इसलिए, नेविगेशन फ़ोकस ऊपर से नीचे और नीचे से ऊपर की ओर साइकल करेगा.

अगर आपको अपने यूज़र इंटरफ़ेस (यूआई) में किसी View को फ़ोकस किया जा सकने वाला व्यू के तौर पर तय करना है (जबकि आम तौर पर ऐसा नहीं होता), तो अपने लेआउट के एलान में, View में android:focusable एक्सएमएल एट्रिब्यूट जोड़ें. इसकी वैल्यू true पर सेट करें. android:focusableInTouchMode की मदद से, टच मोड में भी किसी View को फ़ोकस किया जा सकने वाला व्यू के तौर पर तय किया जा सकता है.

किसी खास View को फ़ोकस करने का अनुरोध करने के लिए, requestFocus() को कॉल करें.

फ़ोकस इवेंट को सुनने के लिए (जब किसी View को फ़ोकस मिलता है या फ़ोकस हटता है, तो सूचना पाने के लिए), onFocusChange(), का इस्तेमाल करें, जैसा कि इवेंट लिसनर सेक्शन में बताया गया है.