जेस्चर वाला नेविगेशन और एक से दूसरे किनारे तक का अनुभव

1. परिचय

Android 10 या इसके बाद के वर्शन के लिए, नेविगेशन के जेस्चर को नए मोड के तौर पर इस्तेमाल किया जा सकता है. इससे आपका ऐप्लिकेशन पूरी स्क्रीन का इस्तेमाल कर पाता है और आपको बेहतर डिसप्ले अनुभव मिलता है. जब उपयोगकर्ता स्क्रीन के सबसे नीचे वाले किनारे से ऊपर की ओर स्वाइप करता है, तो उसे Android की होम स्क्रीन पर ले जाया जाता है. जब उपयोगकर्ता स्क्रीन के बाएं या दाएं किनारे से अंदर की ओर स्वाइप करते हैं, तो उन्हें पिछली स्क्रीन पर ले जाया जाता है.

इन दोनों जेस्चर की मदद से, आपका ऐप्लिकेशन स्क्रीन के सबसे नीचे मौजूद जगह का फ़ायदा उठा सकता है. हालांकि, अगर आपका ऐप्लिकेशन जेस्चर का इस्तेमाल करता है या उसमें सिस्टम जेस्चर वाले इलाकों में कंट्रोल मौजूद हैं, तो इससे सिस्टम-वाइड जेस्चर में समस्या आ सकती है.

इस कोडलैब का मकसद, जेस्चर से जुड़ी समस्याओं से बचने के लिए, इनसेट का इस्तेमाल करने का तरीका सिखाना है. इसके अलावा, इस कोडलैब का मकसद आपको यह सिखाना है कि Gesture Exclusion API का इस्तेमाल कैसे किया जाता है. इसका इस्तेमाल उन कंट्रोल के लिए किया जाता है जिन्हें जेस्चर ज़ोन में रखना होता है. जैसे, ड्रैग हैंडल.

आपको क्या सीखने को मिलेगा

  • व्यू पर इनसेट लिसनर इस्तेमाल करने का तरीका
  • Gesture Exclusion API का इस्तेमाल करने का तरीका
  • हावभाव की सुविधा चालू होने पर, इमर्सिव मोड कैसे काम करता है

इस कोडलैब का मकसद, आपके ऐप्लिकेशन को सिस्टम के जेस्चर के साथ काम करने लायक बनाना है. इसमें काम के न होने वाले कॉन्सेप्ट और कोड ब्लॉक को हटा दिया जाता है. साथ ही, आपको कॉपी करके चिपकाने के लिए कॉन्सेप्ट और कोड ब्लॉक उपलब्ध कराए जाते हैं.

आपको क्या बनाने को मिलेगा

यूनिवर्सल Android म्यूज़िक प्लेयर (यूएएमपी), Android के लिए एक म्यूज़िक प्लेयर ऐप्लिकेशन का उदाहरण है. इसे Kotlin में लिखा गया है. आपको जेस्चर वाले नेविगेशन के लिए, UAMP सेट अप करना होगा.

  • कंट्रोल को जेस्चर वाले एरिया से दूर ले जाने के लिए, इनसेट का इस्तेमाल करना
  • ऐसे कंट्रोल के लिए बैक जेस्चर से ऑप्ट आउट करने के लिए, Gesture Exclusion API का इस्तेमाल करें जिनमें टकराव होता है
  • हाथ के जेस्चर वाले नेविगेशन के साथ इमर्सिव मोड के व्यवहार में हुए बदलावों के बारे में जानने के लिए, अपनी बिल्ड का इस्तेमाल करना

आपको इन चीज़ों की ज़रूरत होगी

  • Android 10 या इसके बाद के वर्शन पर काम करने वाला डिवाइस या एम्युलेटर
  • Android Studio

2. ऐप्लिकेशन की खास जानकारी

यूनिवर्सल Android म्यूज़िक प्लेयर (यूएएमपी), Android के लिए एक सैंपल म्यूज़िक प्लेयर ऐप्लिकेशन है. इसे Kotlin में लिखा गया है. यह बैकग्राउंड में चलाने, ऑडियो फ़ोकस को मैनेज करने, Assistant के साथ इंटिग्रेट करने, और Wear, TV, और Auto जैसे कई प्लैटफ़ॉर्म पर काम करता है.

पहली इमेज: UAMP में एक फ़्लो

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

3. सेट अप करें

सैंपल ऐप्लिकेशन पाने के लिए, GitHub से रिपॉज़िटरी का क्लोन बनाएं और starter ब्रांच पर स्विच करें:

$  git clone https://github.com/googlecodelabs/android-gestural-navigation/

इसके अलावा, रिपॉज़िटरी को zip फ़ाइल के तौर पर डाउनलोड किया जा सकता है. इसके बाद, इसे अनज़िप करके Android Studio में खोला जा सकता है.

यहां दिया गया तरीका अपनाएं:

  1. Android Studio में ऐप्लिकेशन खोलें और उसे बनाएं.
  2. नया वर्चुअल डिवाइस बनाएं और एपीआई लेवल 29 चुनें. इसके अलावा, एपीआई लेवल 29 या उसके बाद के वर्शन पर काम करने वाले किसी डिवाइस को कनेक्ट किया जा सकता है.
  3. ऐप्लिकेशन चलाएं. आपको सुझाए गए और एल्बम सेक्शन में, गानों की सूची दिखेगी.
  4. सुझाया गया पर क्लिक करें और गानों की सूची से कोई गाना चुनें.
  5. ऐप्लिकेशन में गाना बजना शुरू हो जाता है.

जेस्चर वाला नेविगेशन चालू करना

अगर आपने एपीआई लेवल 29 के साथ नया एम्युलेटर इंस्टेंस चलाया है, तो हो सकता है कि जेस्चर नेविगेशन डिफ़ॉल्ट रूप से चालू न हो. जेस्चर वाला नेविगेशन चालू करने के लिए, सिस्टम सेटिंग > सिस्टम > सिस्टम नेविगेशन > जेस्चर वाला नेविगेशन को चुनें.

जेस्चर वाले नेविगेशन की मदद से ऐप्लिकेशन चलाना

अगर आपने हाथ के जेस्चर (स्पर्श) वाला नेविगेशन चालू किया है और कोई गाना चलाया है, तो आपको दिख सकता है कि प्लेयर कंट्रोल, होम पेज और वापस जाने के जेस्चर वाले एरिया के बहुत करीब हैं.

4. एज-टू-एज डिसप्ले की सुविधा चालू करना

एज-टू-एज क्या होता है?

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

नेविगेशन बार के पीछे ड्रॉ करें

नेविगेशन बार के नीचे कॉन्टेंट रेंडर करने के लिए, आपको सबसे पहले नेविगेशन बार के बैकग्राउंड को पारदर्शी बनाना होगा. इसके बाद, आपको स्टेटस बार को पारदर्शी बनाना होगा. इससे आपका ऐप्लिकेशन, स्क्रीन की पूरी ऊंचाई पर दिखता है.

नेविगेशन बार और स्टेटस बार का रंग बदलने के लिए, यह तरीका अपनाएं:

  1. नेविगेशन बार: res/values-29/styles.xml खोलें और navigationBarColor को color/transparent पर सेट करें.
  2. स्टेटस बार: इसी तरह, statusBarColor को color/transparent पर सेट करें.

res/values-29/styles.xml का यह कोड सैंपल देखें:

<!-- change navigation bar color -->
<item name="android:navigationBarColor">
    @android:color/transparent
</item>

<!-- change status bar color -->
<item name="android:statusBarColor">
    @android:color/transparent
</item>

सिस्टम यूज़र इंटरफ़ेस (यूआई) की दृश्यता के फ़्लैग

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

  1. MainActivity.kt क्लास खोलें और onCreate() तरीका ढूंढें. fragmentContainer का इंस्टेंस पाएं.
  2. इन्हें content.systemUiVisibility पर सेट करें:

MainActivity.kt का यह कोड सैंपल देखें:

  val content: FrameLayout = findViewById(R.id.fragmentContainer)
  content.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
            View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
            View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

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

  1. ऐप्लिकेशन चलाएं. इसके बाद, प्लेयर स्क्रीन पर जाने के लिए, कोई गाना चलाएं.
  2. पुष्टि करें कि प्लेयर कंट्रोल, नेविगेशन बार के नीचे दिख रहे हों. इससे उन्हें ऐक्सेस करने में मुश्किल होती है:

  1. सिस्टम सेटिंग पर जाएं. इसके बाद, तीन बटन वाले नेविगेशन मोड पर वापस जाएं और ऐप्लिकेशन पर वापस जाएं.
  2. पुष्टि करें कि तीन बटन वाले नेविगेशन बार के साथ कंट्रोल का इस्तेमाल करना और भी मुश्किल है: ध्यान दें कि SeekBar नेविगेशन बार के पीछे छिपा हुआ है और चलाएं/रोकें बटन का ज़्यादातर हिस्सा नेविगेशन बार से ढका हुआ है.
  3. थोड़ा एक्सप्लोर करें और एक्सपेरिमेंट करें. इसके बाद, सिस्टम सेटिंग पर जाएं और जेस्चर वाले नेविगेशन पर वापस जाएं:

741ef664e9be5e7f.gif

अब ऐप्लिकेशन, स्क्रीन के एक किनारे से दूसरे किनारे तक दिखता है. हालांकि, इसमें इस्तेमाल से जुड़ी समस्याएं हैं. साथ ही, ऐप्लिकेशन के कंट्रोल एक-दूसरे से टकराते हैं और ओवरलैप होते हैं. इन समस्याओं को ठीक करना ज़रूरी है.

5. इनसेट

WindowInsets ऐप्लिकेशन को यह जानकारी दें कि सिस्टम यूज़र इंटरफ़ेस (यूआई), आपके कॉन्टेंट के ऊपर कहां दिखता है. साथ ही, यह भी बताएं कि स्क्रीन के किन हिस्सों में, ऐप्लिकेशन में किए जाने वाले जेस्चर के मुकाबले सिस्टम जेस्चर को प्राथमिकता दी जाती है. Jetpack में, इनसेट को WindowInsets क्लास और WindowInsetsCompat क्लास से दिखाया जाता है. हमारा सुझाव है कि आप WindowInsetsCompat का इस्तेमाल करें, ताकि सभी एपीआई लेवल पर एक जैसा व्यवहार हो.

सिस्टम इनसेट और ज़रूरी सिस्टम इनसेट

यहां दिए गए इनसेट एपीआई, सबसे ज़्यादा इस्तेमाल किए जाने वाले इनसेट टाइप हैं:

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

ऐप्लिकेशन कंट्रोल को दूसरी जगह ले जाने के लिए, इनसेट का इस्तेमाल करना

अब जब आपको इनसेट एपीआई के बारे में ज़्यादा जानकारी मिल गई है, तो ऐप्लिकेशन कंट्रोल को ठीक किया जा सकता है. इसके लिए, यहां दिया गया तरीका अपनाएं:

  1. view ऑब्जेक्ट इंस्टेंस से playerLayout का इंस्टेंस पाएं.
  2. playerView में OnApplyWindowInsetsListener जोड़ें.
  3. व्यू को जेस्चर वाले एरिया से दूर ले जाएं: सबसे नीचे के लिए सिस्टम इंसर्ट वैल्यू ढूंढें और व्यू की पैडिंग को उस वैल्यू के हिसाब से बढ़ाएं. व्यू की पैडिंग को अपडेट करने के लिए, [ऐप्लिकेशन की बॉटम पैडिंग से जुड़ी वैल्यू] में [सिस्टम की इंसर्ट बॉटम वैल्यू से जुड़ी वैल्यू] जोड़ें.

NowPlayingFragment.kt का यह कोड सैंपल देखें:

playerView = view.findViewById(R.id.playerLayout)
playerView.setOnApplyWindowInsetsListener { view, insets ->
   view.updatePadding(
      bottom = insets.systemWindowInsetBottom + view.paddingBottom
   )
   insets
}
  1. ऐप्लिकेशन चलाएं और कोई गाना चुनें. ध्यान दें कि प्लेयर कंट्रोल में कोई बदलाव नहीं हुआ है. अगर आपने कोई ब्रेकपॉइंट जोड़ा है और ऐप्लिकेशन को डीबग मोड में चलाया है, तो आपको दिखेगा कि लिसनर को कॉल नहीं किया गया है.
  2. इस समस्या को ठीक करने के लिए, FragmentContainerView पर स्विच करें. यह समस्या को अपने-आप ठीक कर देता है. activity_main.xml खोलें और FrameLayout को FragmentContainerView पर बदलें.

activity_main.xml का यह कोड सैंपल देखें:

<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/fragmentContainer"
    tools:context="com.example.android.uamp.MainActivity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
  1. ऐप्लिकेशन को फिर से चलाएं और प्लेयर स्क्रीन पर जाएं. सबसे नीचे मौजूद प्लेयर कंट्रोल को, सबसे नीचे मौजूद जेस्चर एरिया से हटा दिया गया है.

ऐप्लिकेशन कंट्रोल अब जेस्चर नेविगेशन के साथ काम करते हैं. हालांकि, कंट्रोल उम्मीद से ज़्यादा हिलते हैं. आपको यह समस्या ठीक करनी होगी.

मौजूदा पैडिंग और मार्जिन बनाए रखें

अगर ऐप्लिकेशन को बंद किए बिना, दूसरे ऐप्लिकेशन पर स्विच किया जाता है या होम स्क्रीन पर जाकर वापस ऐप्लिकेशन पर जाया जाता है, तो ध्यान दें कि प्लेयर कंट्रोल हर बार ऊपर की ओर चले जाते हैं.

ऐसा इसलिए होता है, क्योंकि गतिविधि शुरू होने पर ऐप्लिकेशन हर बार requestApplyInsets() को ट्रिगर करता है. इस कॉल के बिना भी, व्यू के लाइफ़साइकल के दौरान WindowInsets को कई बार भेजा जा सकता है.

playerView पर मौजूद मौजूदा InsetListener, पहली बार में सही तरीके से काम करता है. ऐसा तब होता है, जब ऐप्लिकेशन के बॉटम पैडिंग की वैल्यू में, बॉटम वैल्यू के इनसेट की वैल्यू जोड़ी जाती है. यह वैल्यू activity_main.xml में तय की जाती है. हालांकि, इसके बाद किए गए कॉल, पहले से अपडेट किए गए व्यू के बॉटम पैडिंग में, इंसर्ट बॉटम वैल्यू जोड़ते रहते हैं.

इस समस्या को ठीक करने के लिए, यह तरीका अपनाएं:

  1. यह कुकी, शुरुआती व्यू पैडिंग वैल्यू को रिकॉर्ड करती है. एक नया val बनाएं और लिसनर कोड से ठीक पहले, playerView की शुरुआती व्यू पैडिंग वैल्यू सेव करें.

NowPlayingFragment.kt का यह कोड सैंपल देखें:

   val initialPadding = playerView.paddingBottom
  1. इस शुरुआती वैल्यू का इस्तेमाल करके, व्यू की बॉटम पैडिंग को अपडेट करें. इससे आपको ऐप्लिकेशन की मौजूदा बॉटम पैडिंग वैल्यू का इस्तेमाल करने से बचने में मदद मिलती है.

NowPlayingFragment.kt का यह कोड सैंपल देखें:

   playerView.setOnApplyWindowInsetsListener { view, insets ->
            view.updatePadding(bottom = insets.systemWindowInsetBottom + initialPadding)
            insets
        }
  1. ऐप्लिकेशन को फिर से चलाएं. ऐप्लिकेशन के बीच स्विच करना और होम स्क्रीन पर जाना. ऐप्लिकेशन को वापस लाने पर, प्लेयर कंट्रोल जेस्चर एरिया के ठीक ऊपर दिखते हैं.

ऐप्लिकेशन के कंट्रोल को फिर से डिज़ाइन करना

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

इनसेट का इस्तेमाल करके, जेस्चर से जुड़ी समस्याओं को ठीक किया जा सकता है. हालांकि, कभी-कभी डिज़ाइन में छोटे-मोटे बदलाव करके, जेस्चर से जुड़ी समस्याओं को पूरी तरह से ठीक किया जा सकता है. जेस्चर से जुड़ी समस्याओं से बचने के लिए, प्लेयर कंट्रोल को फिर से डिज़ाइन करने के लिए यह तरीका अपनाएं:

  1. fragment_nowplaying.xml खोलें. डिज़ाइन व्यू पर स्विच करें और सबसे नीचे मौजूद SeekBar को चुनें:

74918dec3926293f.png

  1. कोड व्यू पर स्विच करें.
  2. SeekBar को playerLayout के सबसे ऊपर ले जाने के लिए, SeekBar के layout_constraintTop_toBottomOf को parent में बदलें.
  3. playerView में मौजूद अन्य आइटम को SeekBar के सबसे नीचे रखने के लिए, media_button, title, और position पर layout_constraintTop_toTopOf को पैरंट से बदलकर @+id/seekBar करें.

fragment_nowplaying.xml का यह कोड सैंपल देखें:

<androidx.constraintlayout.widget.ConstraintLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:padding="8dp"
   android:layout_gravity="bottom"
   android:background="@drawable/media_overlay_background"
   android:id="@+id/playerLayout">

   <ImageButton
       android:id="@+id/media_button"
       android:layout_width="@dimen/exo_media_button_width"
       android:layout_height="@dimen/exo_media_button_height"
       android:background="?attr/selectableItemBackground"
       android:scaleType="centerInside"
       app:layout_constraintLeft_toLeftOf="parent"
       app:layout_constraintTop_toTopOf="@+id/seekBar"
       app:srcCompat="@drawable/ic_play_arrow_black_24dp"
       tools:ignore="ContentDescription" />

   <TextView
       android:id="@+id/title"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_marginTop="8dp"
       android:layout_marginStart="@dimen/text_margin"
       android:layout_marginEnd="@dimen/text_margin"
       android:ellipsize="end"
       android:maxLines="1"
       android:textAppearance="@style/TextAppearance.Uamp.Title"
       app:layout_constraintTop_toTopOf="@+id/seekBar"
       app:layout_constraintLeft_toRightOf="@id/media_button"
       app:layout_constraintRight_toLeftOf="@id/position"
       tools:text="Song Title" />

   <TextView
       android:id="@+id/subtitle"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_marginStart="@dimen/text_margin"
       android:layout_marginEnd="@dimen/text_margin"
       android:ellipsize="end"
       android:maxLines="1"
       android:textAppearance="@style/TextAppearance.Uamp.Subtitle"
       app:layout_constraintTop_toBottomOf="@+id/title"
       app:layout_constraintLeft_toRightOf="@id/media_button"
       app:layout_constraintRight_toLeftOf="@id/position"
       tools:text="Artist" />

   <TextView
       android:id="@+id/position"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_marginTop="8dp"
       android:layout_marginStart="@dimen/text_margin"
       android:layout_marginEnd="@dimen/text_margin"
       android:ellipsize="end"
       android:maxLines="1"
       android:textAppearance="@style/TextAppearance.Uamp.Title"
       app:layout_constraintTop_toTopOf="@+id/seekBar"
       app:layout_constraintRight_toRightOf="parent"
       tools:text="0:00" />

   <TextView
       android:id="@+id/duration"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_marginStart="@dimen/text_margin"
       android:layout_marginEnd="@dimen/text_margin"
       android:ellipsize="end"
       android:maxLines="1"
       android:textAppearance="@style/TextAppearance.Uamp.Subtitle"
       app:layout_constraintTop_toBottomOf="@id/position"
       app:layout_constraintRight_toRightOf="parent"
       tools:text="0:00" />

   <SeekBar
       android:id="@+id/seekBar"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
  1. ऐप्लिकेशन चलाएं और प्लेयर और सीकबार के साथ इंटरैक्ट करें.

डिज़ाइन में किए गए इन मामूली बदलावों से, ऐप्लिकेशन की परफ़ॉर्मेंस में काफ़ी सुधार हुआ है.

6. Gesture Exclusion API

होम जेस्चर एरिया में, जेस्चर से जुड़ी समस्याओं के लिए प्लेयर कंट्रोल ठीक कर दिए गए हैं. बैक जेस्चर वाली जगह, ऐप्लिकेशन के कंट्रोल के साथ भी टकराव पैदा कर सकती है. इस स्क्रीनशॉट में दिखाया गया है कि प्लेयर की सीकबार, फ़िलहाल बैक जेस्चर के लिए दाईं और बाईं, दोनों जगहों पर मौजूद है:

e6d98e94dcf83dde.png

SeekBar, जेस्चर से जुड़े विवादों को अपने-आप मैनेज करता है. हालांकि, आपको ऐसे अन्य यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट इस्तेमाल करने पड़ सकते हैं जो जेस्चर से जुड़ी समस्याएं ट्रिगर करते हैं. ऐसे मामलों में, Gesture Exclusion API का इस्तेमाल करके, बैक जेस्चर से कुछ हद तक ऑप्ट आउट किया जा सकता है.

Gesture Exclusion API का इस्तेमाल करना

जेस्चर एक्सक्लूज़न ज़ोन बनाने के लिए, अपनी व्यू पर setSystemGestureExclusionRects() को कॉल करें. इसके साथ ही, rect ऑब्जेक्ट की सूची भी दें. ये rect ऑब्जेक्ट, बाहर रखे गए आयताकार क्षेत्रों के निर्देशांकों पर मैप करते हैं. यह कॉल, व्यू के onLayout() या onDraw() तरीकों से किया जाना चाहिए. ऐसा करने के लिए, यह तरीका अपनाएं:

  1. view नाम का नया पैकेज बनाएं.
  2. इस एपीआई को कॉल करने के लिए, MySeekBar नाम की नई क्लास बनाएं और AppCompatSeekBar को बढ़ाएं.

MySeekBar.kt का यह कोड सैंपल देखें:

class MySeekBar @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = android.R.attr.seekBarStyle
) : androidx.appcompat.widget.AppCompatSeekBar(context, attrs, defStyle) {

}
  1. updateGestureExclusion() नाम का एक नया तरीका बनाएं.

MySeekBar.kt का यह कोड सैंपल देखें:

private fun updateGestureExclusion() {

}
  1. एपीआई लेवल 28 या इससे पहले के लेवल पर इस कॉल को स्किप करने के लिए, एक चेक जोड़ें.

MySeekBar.kt का यह कोड सैंपल देखें:

private fun updateGestureExclusion() {
        // Skip this call if we're not running on Android 10+
        if (Build.VERSION.SDK_INT < 29) return
}
  1. Gesture Exclusion API में 200 डीपी की सीमा होती है. इसलिए, सिर्फ़ सीकबार के थंब को बाहर रखें. सीकबार की सीमाओं की कॉपी पाएं और हर ऑब्जेक्ट को बदलाव की अनुमति वाली सूची में जोड़ें.

MySeekBar.kt का यह कोड सैंपल देखें:

private val gestureExclusionRects = mutableListOf<Rect>()

private fun updateGestureExclusion() {
    // Skip this call if we're not running on Android 10+
    if (Build.VERSION.SDK_INT < 29) return

    thumb?.also { t ->
        gestureExclusionRects += t.copyBounds()
    }
}
  1. आपने जो gestureExclusionRects सूचियां बनाई हैं उनका इस्तेमाल करके, systemGestureExclusionRects() को कॉल करें.

MySeekBar.kt का यह कोड सैंपल देखें:

private val gestureExclusionRects = mutableListOf<Rect>()

private fun updateGestureExclusion() {
    // Skip this call if we're not running on Android 10+
    if (Build.VERSION.SDK_INT < 29) return

    thumb?.also { t ->
        gestureExclusionRects += t.copyBounds()
    }
    // Finally pass our updated list of rectangles to the system
    systemGestureExclusionRects = gestureExclusionRects
}
  1. onDraw() या onLayout() से updateGestureExclusion() वाले तरीके को कॉल करें. onDraw() को बदलें और updateGestureExclusion में कॉल जोड़ें.

MySeekBar.kt का यह कोड सैंपल देखें:

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    updateGestureExclusion()
}
  1. आपको SeekBar के रेफ़रंस अपडेट करने होंगे. शुरू करने के लिए, fragment_nowplaying.xml खोलें.
  2. SeekBar को com.example.android.uamp.view.MySeekBar में बदलें.

fragment_nowplaying.xml का यह कोड सैंपल देखें:

<com.example.android.uamp.view.MySeekBar
    android:id="@+id/seekBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="parent" />
  1. NowPlayingFragment.kt में SeekBar के रेफ़रंस अपडेट करने के लिए, NowPlayingFragment.kt खोलें और positionSeekBar के टाइप को MySeekBar में बदलें. वैरिएबल टाइप से मैच करने के लिए, findViewById कॉल के लिए SeekBar जेनेरिक को MySeekBar में बदलें.

NowPlayingFragment.kt का यह कोड सैंपल देखें:

val positionSeekBar: MySeekBar = view.findViewById<MySeekBar>(
     R.id.seekBar
).apply { progress = 0 }
  1. ऐप्लिकेशन चलाएं और SeekBar के साथ इंटरैक्ट करें. अगर आपको अब भी जेस्चर से जुड़ी समस्याएं आ रही हैं, तो MySeekBar में जाकर, थंब बाउंड्री में बदलाव किया जा सकता है. ध्यान रखें कि जेस्चर एक्सक्लूज़न ज़ोन को ज़रूरत से ज़्यादा बड़ा न बनाएं. ऐसा इसलिए, क्योंकि इससे जेस्चर एक्सक्लूज़न के अन्य संभावित कॉल सीमित हो जाते हैं. साथ ही, उपयोगकर्ता के लिए एक जैसा व्यवहार नहीं होता.

7. बधाई हो

बधाई हो! आपने सिस्टम के जेस्चर से जुड़ी समस्याओं से बचने और उन्हें हल करने का तरीका जान लिया है!

आपने अपने ऐप्लिकेशन को फ़ुल-स्क्रीन मोड में इस्तेमाल करने के लिए सेट किया है. इसके लिए, आपने एज-टू-एज लेआउट का इस्तेमाल किया है. साथ ही, ऐप्लिकेशन के कंट्रोल को जेस्चर ज़ोन से दूर ले जाने के लिए, इनसेट का इस्तेमाल किया है. आपने ऐप्लिकेशन कंट्रोल पर, सिस्टम के बैक जेस्चर की सुविधा बंद करने का तरीका भी सीखा.

अब आपको सिस्टम के जेस्चर के साथ अपने ऐप्लिकेशन को काम करने के लिए ज़रूरी मुख्य चरणों के बारे में पता चल गया है!

अन्य संसाधन

रेफ़रंस दस्तावेज़