वीडियो के विषय से जुड़े मुख्य कॉन्सेप्ट

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

यहां दिए गए सेक्शन में, ड्रैग-एंड-ड्रॉप प्रोसेस से जुड़े कुछ अहम कॉन्सेप्ट के बारे में बताया गया है.

खींचने और छोड़ने की प्रोसेस

ड्रैग-एंड-ड्रॉप प्रोसेस में चार चरण या स्थितियां होती हैं: शुरू हुई, जारी है, छोड़ दी गई, और खत्म हो गई.

शुरू किया गया

उपयोगकर्ता के खींचने वाले जेस्चर के जवाब में, आपका ऐप्लिकेशन startDragAndDrop() को कॉल करता है, ताकि सिस्टम को ड्रैग-एंड-ड्रॉप ऑपरेशन शुरू करने के लिए कहा जा सके. इस तरीके के आर्ग्युमेंट से ये जानकारी मिलती है:

  • ड्रैग किया जाने वाला डेटा.
  • ड्रैग शैडो बनाने के लिए कॉलबैक
  • मेटाडेटा, जो ड्रैग किए गए डेटा के बारे में बताता है
  • सिस्टम, आपके ऐप्लिकेशन को वापस कॉल करके, ड्रैग शैडो पाने का अनुरोध करता है. इसके बाद, सिस्टम डिवाइस पर ड्रैग शैडो दिखाता है.
  • इसके बाद, सिस्टम, मौजूदा लेआउट में मौजूद सभी View ऑब्जेक्ट के ड्रैग इवेंट लिसनर को, ऐक्शन टाइप ACTION_DRAG_STARTED वाला ड्रैग इवेंट भेजता है. ड्रैग इवेंट की सूचनाएं पाने के लिए, ड्रैग इवेंट लिसनर को true वैल्यू वापस भेजनी होगी. इसमें ड्रॉप इवेंट भी शामिल है. यह सिस्टम के साथ लिसनर को रजिस्टर करता है. सिर्फ़ रजिस्टर किए गए लिसनर को ड्रैग इवेंट मिलते हैं. इस समय, लिसनर अपने ड्रॉप टारगेट View ऑब्जेक्ट के दिखने के तरीके को भी बदल सकते हैं, ताकि यह दिखाया जा सके कि व्यू, ड्रॉप इवेंट को स्वीकार कर सकता है.
  • अगर ड्रैग इवेंट लिसनर, false दिखाता है, तो उसे मौजूदा ऑपरेशन के लिए ड्रैग इवेंट नहीं मिलते. ऐसा तब तक होता है, जब तक सिस्टम ACTION_DRAG_ENDED ऐक्शन टाइप वाला ड्रैग इवेंट नहीं भेजता. false को वापस लाने पर, लिसनर सिस्टम को बताता है कि उसे ड्रैग-एंड-ड्रॉप ऑपरेशन में कोई दिलचस्पी नहीं है और वह ड्रैग किए गए डेटा को स्वीकार नहीं करना चाहता.
जारी है
उपयोगकर्ता, आइटम को खींचना जारी रखता है. ड्रैग शैडो, ड्रॉप टारगेट के बाउंडिंग बॉक्स को इंटरसेक्ट करती है. इसलिए, सिस्टम टारगेट के ड्रैग इवेंट लिसनर को एक या उससे ज़्यादा ड्रैग इवेंट भेजता है. लिसनर, इवेंट के जवाब में ड्रॉप टारगेट View की उपस्थिति में बदलाव कर सकता है. उदाहरण के लिए, अगर इवेंट से पता चलता है कि ड्रैग शैडो, ड्रॉप टारगेट के बाउंडिंग बॉक्स में शामिल हो गई है—कार्रवाई का टाइप ACTION_DRAG_ENTERED —तो लिसनर, View को हाइलाइट करके प्रतिक्रिया दे सकता है.
प्रेषित
उपयोगकर्ता, ड्रॉप टारगेट के बाउंडिंग बॉक्स में ड्रैग शैडो छोड़ता है. सिस्टम, ड्रॉप टारगेट के लिसनर को ACTION_DROP ऐक्शन टाइप वाला ड्रैग इवेंट भेजता है. ड्रैग इवेंट ऑब्जेक्ट में वह डेटा होता है जो सिस्टम को startDragAndDrop() कॉल में पास होता है. यह कॉल, ऑपरेशन शुरू करता है. अगर लिसनर, ड्रॉप किए गए डेटा को प्रोसेस कर लेता है, तो उसे सिस्टम को बूलियन वैल्यू true दिखानी होती है. : यह चरण सिर्फ़ तब होता है, जब उपयोगकर्ता ड्रैग शैडो को View के बाउंडिंग बॉक्स में छोड़ता है. इस View के लिसनर को ड्रैग इवेंट पाने के लिए रजिस्टर किया जाता है (ड्रॉप टारगेट). अगर उपयोगकर्ता किसी अन्य स्थिति में ड्रैग शैडो छोड़ता है, तो ACTION_DROP ड्रैग इवेंट नहीं भेजा जाता है.
खत्म

जब उपयोगकर्ता ड्रैग शैडो छोड़ देता है और सिस्टम

ACTION_DROP ऐक्शन टाइप वाला ड्रैग इवेंट पूरा होने के बाद, सिस्टम ACTION_DRAG_ENDED ऐक्शन टाइप वाला ड्रैग इवेंट भेजता है. इससे पता चलता है कि ड्रैग-एंड-ड्रॉप ऑपरेशन पूरा हो गया है. इससे कोई फ़र्क़ नहीं पड़ता कि उपयोगकर्ता ड्रैग शैडो को कहां छोड़ता है. इस इवेंट को हर उस लिसनर को भेजा जाता है जिसने ड्रैग इवेंट पाने के लिए रजिस्टर किया है. भले ही, लिसनर को ACTION_DROP इवेंट भी मिलता हो.

इनमें से हर चरण के बारे में ज़्यादा जानकारी, ड्रैग-एंड-ड्रॉप ऑपरेशन सेक्शन में दी गई है.

ड्रैग इवेंट

सिस्टम, ड्रैग इवेंट को DragEvent ऑब्जेक्ट के तौर पर भेजता है. इसमें ऐक्शन टाइप होता है, जिससे ड्रैग-एंड-ड्रॉप प्रोसेस में होने वाली गतिविधि के बारे में पता चलता है. कार्रवाई के टाइप के आधार पर, ऑब्जेक्ट में अन्य डेटा भी शामिल हो सकता है.

ड्रैग इवेंट लिसनर को DragEvent ऑब्जेक्ट मिलता है. कार्रवाई का टाइप पाने के लिए, श्रोता DragEvent.getAction() पर कॉल करते हैं. DragEvent क्लास में, छह वैल्यू तय की गई हैं. इनके बारे में टेबल 1 में बताया गया है:

पहली टेबल. DragEvent के ऐक्शन टाइप

कार्रवाई प्रकार मतलब
ACTION_DRAG_STARTED ऐप्लिकेशन, startDragAndDrop() को कॉल करता है और ड्रैग शैडो हासिल करता है. अगर लिसनर को इस कार्रवाई के लिए, ड्रैग इवेंट मिलते रहने चाहिए, तो उसे सिस्टम को बूलियन true वैल्यू देनी होगी.
ACTION_DRAG_ENTERED ड्रैग शैडो, ड्रैग इवेंट लिसनर के बाउंडिंग बॉक्स View में शामिल हो जाती है. यह पहला इवेंट ऐक्शन टाइप है, जो लिसनर को तब मिलता है, जब ड्रैग शैडो बाउंडिंग बॉक्स में एंटर करती है.
ACTION_DRAG_LOCATION ACTION_DRAG_ENTERED इवेंट के बाद, ड्रैग शैडो अब भी ड्रैग इवेंट लिसनर के View के बाउंडिंग बॉक्स में है.
ACTION_DRAG_EXITED ACTION_DRAG_ENTERED और कम से कम एक ACTION_DRAG_LOCATION इवेंट के बाद, ड्रैग शैडो, ड्रैग इवेंट लिसनर के View के बाउंडिंग बॉक्स से बाहर चला जाता है.
ACTION_DROP ड्रैग शैडो, ड्रैग इवेंट लिसनर के View पर रिलीज़ होती है. इस तरह की कार्रवाई, View ऑब्जेक्ट के लिसनर को सिर्फ़ तब भेजी जाती है, जब लिसनर, ACTION_DRAG_STARTED ड्रैग इवेंट के जवाब में बूलियन true दिखाता है. अगर उपयोगकर्ता, ड्रैग शैडो को ऐसे View पर छोड़ता है जिसका लिसनर रजिस्टर नहीं है या अगर उपयोगकर्ता, ड्रैग शैडो को मौजूदा लेआउट का हिस्सा न होने वाली किसी चीज़ पर छोड़ता है, तो इस तरह की कार्रवाई नहीं भेजी जाती.

अगर लिसनर, ड्रॉप को प्रोसेस कर लेता है, तो वह true वैल्यू दिखाता है. अगर ऐसा नहीं है, तो इसे false दिखाना होगा.

ACTION_DRAG_ENDED सिस्टम, ड्रैग-एंड-ड्रॉप ऑपरेशन को खत्म कर रहा है. इस ऐक्शन टाइप से पहले, ACTION_DROP इवेंट होना ज़रूरी नहीं है. अगर सिस्टम ACTION_DROP भेजता है, तो ACTION_DRAG_ENDED ऐक्शन टाइप मिलने का मतलब यह नहीं है कि ड्रॉप हो गया है. लिसनर को getResult() को कॉल करना होगा, जैसा कि table 2 में दिखाया गया है. इससे, उसे वह वैल्यू मिलेगी जो ACTION_DROP के जवाब में दिखाई गई है. अगर ACTION_DROP इवेंट नहीं भेजा जाता है, तो getResult(), false दिखाता है.

DragEvent ऑब्जेक्ट में वह डेटा और मेटाडेटा भी शामिल होता है जो आपका ऐप्लिकेशन, startDragAndDrop() को कॉल करने के दौरान सिस्टम को देता है. कुछ डेटा सिर्फ़ कुछ कार्रवाइयों के लिए मान्य होता है. इसकी जानकारी टेबल 2 में दी गई है. इवेंट और उनसे जुड़े डेटा के बारे में ज़्यादा जानने के लिए, ड्रैग-एंड-ड्रॉप ऑपरेशन सेक्शन देखें.

टेबल 2. कार्रवाई के टाइप के हिसाब से, DragEvent का मान्य डेटा

getAction()
value
getClipDescription()
value
getLocalState()
value
getX()
value
getY()
value
getClipData()
value
getResult()
value
ACTION_DRAG_STARTED ✓ ✓        
ACTION_DRAG_ENTERED ✓ ✓        
ACTION_DRAG_LOCATION ✓ ✓ ✓ ✓    
ACTION_DRAG_EXITED ✓ ✓        
ACTION_DROP ✓ ✓ ✓ ✓ ✓  
ACTION_DRAG_ENDED   ✓       ✓

DragEvent के getAction(), describeContents(), writeToParcel(), और toString() तरीके हमेशा मान्य डेटा दिखाते हैं.

अगर किसी तरीके में, किसी खास ऐक्शन टाइप के लिए मान्य डेटा नहीं है, तो वह null या 0 दिखाता है. यह इस बात पर निर्भर करता है कि उसका नतीजा किस तरह का है.

ड्रैग शैडो

ड्रैग-एंड-ड्रॉप ऑपरेशन के दौरान, सिस्टम एक ऐसी इमेज दिखाता है जिसे उपयोगकर्ता ड्रैग करता है. डेटा को एक जगह से दूसरी जगह ले जाने के लिए, इस इमेज में डेटा को ड्रैग करते हुए दिखाया गया है. अन्य कार्रवाइयों के लिए, इमेज में ड्रैग करने की कार्रवाई का कोई पहलू दिखाया जाता है.

इस इमेज को ड्रैग शैडो कहा जाता है. इसे View.DragShadowBuilder ऑब्जेक्ट के लिए तय किए गए तरीकों से बनाया जाता है. startDragAndDrop() का इस्तेमाल करके, ड्रैग-एंड-ड्रॉप ऑपरेशन शुरू करने पर, बिल्डर को सिस्टम में पास किया जाता है. startDragAndDrop() के जवाब के तौर पर, सिस्टम View.DragShadowBuilder में तय किए गए कॉलबैक तरीकों को लागू करता है, ताकि ड्रैग शैडो मिल सके.

View.DragShadowBuilder क्लास में दो कंस्ट्रक्टर होते हैं:

View.DragShadowBuilder(View)

यह कंस्ट्रक्टर, आपके ऐप्लिकेशन के किसी भी View ऑब्जेक्ट को स्वीकार करता है. कंस्ट्रक्टर, View ऑब्जेक्ट को View.DragShadowBuilder ऑब्जेक्ट में सेव करता है, ताकि कॉलबैक इसे ऐक्सेस करके ड्रैग शैडो बना सकें. यह ज़रूरी नहीं है कि व्यू, View हो. यह वह व्यू होना चाहिए जिसे उपयोगकर्ता ने खींचने की कार्रवाई शुरू करने के लिए चुना है.

इस कंस्ट्रक्टर का इस्तेमाल करने पर, आपको View.DragShadowBuilder को बढ़ाने या इसके तरीकों को बदलने की ज़रूरत नहीं होती. डिफ़ॉल्ट रूप से, आपको एक ड्रैग शैडो मिलती है. यह View के जैसा दिखता है. इसे आर्ग्युमेंट के तौर पर पास किया जाता है. यह उस जगह के नीचे बीच में होता है जहां उपयोगकर्ता स्क्रीन को छूता है.

View.DragShadowBuilder()

इस कंस्ट्रक्टर का इस्तेमाल करने पर, View.DragShadowBuilder ऑब्जेक्ट में कोई View ऑब्जेक्ट उपलब्ध नहीं होता. इस फ़ील्ड को null पर सेट किया गया है. आपको View.DragShadowBuilder को बढ़ाना होगा और इसके तरीकों को बदलना होगा. ऐसा न करने पर, आपको ड्रैग शैडो नहीं दिखेगी. सिस्टम कोई गड़बड़ी नहीं दिखाता है.

View.DragShadowBuilder क्लास में दो ऐसे तरीके होते हैं जिनसे ड्रैग शैडो बनती है:

onProvideShadowMetrics()

startDragAndDrop() को कॉल करने के तुरंत बाद, सिस्टम इस तरीके को कॉल करता है. इस तरीके का इस्तेमाल करके, सिस्टम को ड्रैग शैडो के डाइमेंशन और टच पॉइंट भेजे जा सकते हैं. इस तरीके में दो पैरामीटर होते हैं:

outShadowSize: एक Point ऑब्जेक्ट. ड्रैग शैडो की चौड़ाई x में और इसकी ऊंचाई y में जाती है.

outShadowTouchPoint: एक Point ऑब्जेक्ट. टच पॉइंट, ड्रैग शैडो के अंदर मौजूद वह जगह होती है जिसे ड्रैग करते समय उपयोगकर्ता की उंगली के नीचे होना चाहिए. इसकी X पोज़िशन x में और Y पोज़िशन y में जाती है.

onDrawShadow()

onProvideShadowMetrics() को कॉल करने के तुरंत बाद, सिस्टम onDrawShadow() को कॉल करता है, ताकि ड्रैग शैडो बनाई जा सके. इस तरीके में एक ही आर्ग्युमेंट होता है, जो Canvas ऑब्जेक्ट होता है. सिस्टम इस ऑब्जेक्ट को, onProvideShadowMetrics() में दिए गए पैरामीटर से बनाता है. यह तरीका, दिए गए Canvas पर ड्रैग शैडो बनाता है.

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

ड्रैग इवेंट लिसनर और कॉलबैक के तरीके

View को ड्रैग इवेंट मिलते हैं. इसके लिए, ड्रैग इवेंट लिसनर का इस्तेमाल किया जाता है. यह लिसनर, View.OnDragListener को लागू करता है. इसके अलावा, व्यू की onDragEvent() कॉलबैक विधि का इस्तेमाल करके भी ड्रैग इवेंट पाए जा सकते हैं. जब सिस्टम, तरीके या लिसनर को कॉल करता है, तो वह DragEvent आर्ग्युमेंट देता है.

ज़्यादातर मामलों में, कॉलबैक तरीके के बजाय लिसनर का इस्तेमाल करना बेहतर होता है. यूज़र इंटरफ़ेस डिज़ाइन करते समय, आम तौर पर View क्लास की सबक्लास नहीं बनाई जाती हैं. हालांकि, कॉलबैक तरीके का इस्तेमाल करने पर, आपको मेथड को बदलने के लिए सबक्लास बनानी पड़ती हैं. इसकी तुलना में, एक लिसनर क्लास को लागू किया जा सकता है. इसके बाद, इसका इस्तेमाल अलग-अलग View ऑब्जेक्ट के साथ किया जा सकता है. इसे किसी गुमनाम इनलाइन क्लास या लैम्डा एक्सप्रेशन के तौर पर भी लागू किया जा सकता है. View ऑब्जेक्ट के लिए लिसनर सेट करने के लिए, setOnDragListener() को कॉल करें.

इसके अलावा, onDragEvent() के डिफ़ॉल्ट इंप्लिमेंटेशन में बदलाव किया जा सकता है. इसके लिए, आपको तरीके को ओवरराइड करने की ज़रूरत नहीं है. किसी व्यू पर OnReceiveContentListener सेट करें. ज़्यादा जानकारी के लिए, setOnReceiveContentListener() देखें. इसके बाद, onDragEvent() तरीका डिफ़ॉल्ट रूप से ये काम करता है:

  • startDragAndDrop() को कॉल करने पर, यह फ़ंक्शन सही वैल्यू दिखाता है.
  • कॉल performReceiveContent() अगर ड्रैग-एंड-ड्रॉप किए गए डेटा को व्यू पर छोड़ दिया जाता है. डेटा को ContentInfo ऑब्जेक्ट के तौर पर, इस तरीके में पास किया जाता है. यह तरीका, OnReceiveContentListener को ट्रिगर करता है.

  • अगर खींचकर छोड़े गए डेटा को व्यू पर छोड़ दिया जाता है और OnReceiveContentListener उस डेटा का इस्तेमाल करता है, तो यह फ़ंक्शन सही वैल्यू दिखाता है.

अपने ऐप्लिकेशन के लिए डेटा को मैनेज करने के लिए, OnReceiveContentListener को तय करें. एपीआई लेवल 24 तक के साथ काम करने वाले वर्शन के लिए, OnReceiveContentListener के Jetpack वर्शन का इस्तेमाल करें.

आपके पास View ऑब्जेक्ट के लिए, ड्रैग इवेंट लिसनर और कॉलबैक तरीका हो सकता है. ऐसे में, सिस्टम सबसे पहले लिसनर को कॉल करता है. जब तक लिसनर false नहीं दिखाता, तब तक सिस्टम कॉलबैक तरीके को कॉल नहीं करता.

onDragEvent() तरीके और View.OnDragListener का कॉम्बिनेशन, टच इवेंट के साथ इस्तेमाल किए जाने वाले onTouchEvent() और View.OnTouchListener के कॉम्बिनेशन के जैसा होता है.