इन सेक्शन में, खींचकर छोड़ने की प्रोसेस के कुछ मुख्य कॉन्सेप्ट के बारे में बताया गया है.
खींचें और छोड़ें सुविधा
'खींचें और छोड़ें' प्रोसेस में चार चरण या स्थितियां होती हैं: शुरू की गई, जारी है, छोड़ी गई, और खत्म हो गई.
- शुरू किया गया
- उपयोगकर्ता के खींचने के जेस्चर के जवाब में, आपका ऐप्लिकेशन - startDragAndDrop()को कॉल करता है, ताकि सिस्टम को खींचने और छोड़ने की कार्रवाई शुरू करने के लिए कहा जा सके. विधेय के आर्ग्युमेंट से ये चीज़ें मिलती हैं:- जिस डेटा को खींचा और छोड़ा जाना है.
- खींचकर छोड़ने पर दिखने वाली परछाई को ड्रॉ करने के लिए कॉलबैक
- खींचे गए डेटा के बारे में बताने वाला मेटाडेटा
- सिस्टम, ड्रैग शैडो पाने के लिए आपके ऐप्लिकेशन को कॉल करके जवाब देता है. इसके बाद, सिस्टम डिवाइस पर ड्रैग शैडो दिखाता है.
- इसके बाद, सिस्टम मौजूदा लेआउट में मौजूद सभी Viewऑब्जेक्ट के ड्रैग इवेंट के लिसनर को, ऐक्शन टाइपACTION_DRAG_STARTEDवाला ड्रैग इवेंट भेजता है. ड्रैग इवेंट लिसनर कोtrueदिखाना होगा, ताकि ड्रैग इवेंट और ड्रॉप इवेंट की सूचना मिलती रहे. इससे लिसनर को सिस्टम के साथ रजिस्टर किया जाता है. सिर्फ़ रजिस्टर किए गए लिसनर को ही ड्रैग इवेंट मिलते रहेंगे. इस दौरान, दर्शक अपने ड्रॉप टारगेटViewऑब्जेक्ट के दिखने का तरीका भी बदल सकते हैं, ताकि यह दिखाया जा सके कि व्यू में ड्रॉप इवेंट स्वीकार किया जा सकता है.
- अगर ड्रैग इवेंट के लिसनर से falseमिलता है, तो मौजूदा कार्रवाई के लिए उसे ड्रैग इवेंट तब तक नहीं मिलते, जब तक सिस्टम कार्रवाई टाइपACTION_DRAG_ENDEDके साथ ड्रैग इवेंट नहीं भेजता.falseदिखाकर, listener, सिस्टम को बताता है कि उसे खींचकर छोड़ने की सुविधा में दिलचस्पी नहीं है और वह खींचे गए डेटा को स्वीकार नहीं करना चाहता.
 
- प्रोसेस जारी है
- उपयोगकर्ता, आइटम को खींचकर छोड़ता है. जब ड्रैग शैडो, ड्रॉप टारगेट के बाउंडिंग बॉक्स से इंटरसेक्शन करता है, तो सिस्टम टारगेट के ड्रैग इवेंट लिसनर को एक या उससे ज़्यादा ड्रैग इवेंट भेजता है. इवेंट के जवाब में, लिसनर ड्रॉप टारगेट Viewके दिखने के तरीके में बदलाव कर सकता है. उदाहरण के लिए, अगर इवेंट से पता चलता है कि ड्रैग किया गया शैडो, ड्रॉप टारगेट के बाउंडिंग बॉक्स में जा रहा है—कार्रवाई का टाइपACTION_DRAG_ENTERED—तो दर्शकViewको हाइलाइट करके प्रतिक्रिया दे सकता है.
- प्रेषित
- उपयोगकर्ता, ड्रॉप टारगेट के बाउंडिंग बॉक्स में, खींचे गए आइटम को छोड़ देता है. सिस्टम, ड्रॉप टारगेट के लिसनर को ऐक्शन टाइप ACTION_DROPवाला ड्रैग इवेंट भेजता है. ड्रैग इवेंट ऑब्जेक्ट में वह डेटा होता है जोstartDragAndDrop()को कॉल करने पर सिस्टम को भेजा जाता है. इससे ऑपरेशन शुरू होता है. अगर listener, ड्रॉप किए गए डेटा को सही तरीके से प्रोसेस करता है, तो उसे सिस्टम को बूलियनtrueदिखाना चाहिए. : यह चरण सिर्फ़ तब होता है, जब उपयोगकर्ता खींचे गए आइटम के शैडो को किसी ऐसेViewके बाउंडिंग बॉक्स में छोड़ता है जिसका लिसनर, खींचे जाने के इवेंट (ड्रॉप टारगेट) पाने के लिए रजिस्टर किया गया हो. अगर उपयोगकर्ता किसी दूसरी स्थिति में खींचे गए आइटम को छोड़ता है, तो कोईACTION_DROPखींचने का इवेंट नहीं भेजा जाता.
- खत्म
- जब उपयोगकर्ता, ड्रैग किए गए आइटम को छोड़ देता है और सिस्टम - ACTION_DROPकार्रवाई टाइप के साथ एक ड्रैग इवेंट भेजता है. अगर ज़रूरी हो, तो सिस्टम- ACTION_DRAG_ENDEDकार्रवाई टाइप के साथ एक ड्रैग इवेंट भेजता है, ताकि यह पता चल सके कि ड्रैग-एंड-ड्रॉप ऑपरेशन खत्म हो गया है. ऐसा तब भी किया जाता है, जब उपयोगकर्ता ड्रैग शैडो को कहीं भी छोड़ता है. यह इवेंट, ड्रैग इवेंट पाने के लिए रजिस्टर किए गए हर लिसनर को भेजा जाता है. भले ही, लिसनर को- ACTION_DROPइवेंट भी मिले.
इनमें से हर चरण के बारे में ज़्यादा जानकारी, ड्रैग-एंड-ड्रॉप ऑपरेशन सेक्शन में दी गई है.
ड्रैग इवेंट
सिस्टम, DragEvent ऑब्जेक्ट के तौर पर एक ड्रैग इवेंट भेजता है. इसमें एक ऐक्शन टाइप होता है, जो बताता है कि ड्रैग-एंड-ड्रॉप प्रोसेस में क्या हो रहा है. कार्रवाई के टाइप के आधार पर, ऑब्जेक्ट में अन्य डेटा भी हो सकता है.
ड्रैग इवेंट लिसनर को DragEvent ऑब्जेक्ट मिलता है. ऐक्शन टाइप जानने के लिए, दर्शक DragEvent.getAction() पर कॉल करते हैं.
DragEvent क्लास में, पहले से तय वैल्यू के हिसाब से छह वैल्यू तय की गई हैं,
जिनके बारे में टेबल 1 में बताया गया है:
टेबल 1. DragEvent के ऐक्शन टाइप
| कार्रवाई का टाइप | मतलब | 
|---|---|
| ACTION_DRAG_STARTED | ऐप्लिकेशन, startDragAndDrop()को कॉल करता है और
          ड्रैग शैडो पाता है. अगर Listener को इस कार्रवाई के लिए, खींचने और छोड़ने के इवेंट पाना जारी रखना है, तो उसे सिस्टम को बूलियन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पर ड्रैग शैडो को छोड़ता है, तो यह ऐक्शन टाइप नहीं भेजा जाता है. ऐसा तब होता है, जबViewके लिए कोई listener रजिस्टर न किया गया हो या उपयोगकर्ता, ड्रैग शैडो को किसी ऐसी चीज़ पर छोड़ता है जो मौजूदा लेआउट का हिस्सा नहीं है.
            अगर लिसनर, ड्रॉप को प्रोसेस कर लेता है, तो वह बूलियन  | 
| 
          
            ACTION_DRAG_ENDED | सिस्टम, खींचकर छोड़ने की प्रोसेस खत्म कर रहा है. इस तरह के ऐक्शन के लिए, ACTION_DROPइवेंट होना ज़रूरी नहीं है. अगर सिस्टमACTION_DROPभेजता है, तोACTION_DRAG_ENDEDऐक्शन टाइप मिलने का मतलब यह नहीं है कि ड्रॉप हो गया है.ACTION_DROPके रिस्पॉन्स में मिली वैल्यू पाने के लिए, लिसनर कोgetResult()को कॉल करना होगा, जैसा कि टेबल 2 में दिखाया गया है. अगर कोई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()को कॉल करने पर, true दिखाता है.
- अगर व्यू में खींचकर छोड़ा गया डेटा छोड़ा जाता है, तो - performReceiveContent()कॉल करता है. डेटा को- ContentInfoऑब्जेक्ट के तौर पर, विधि में पास किया जाता है. यह तरीका- OnReceiveContentListenerको ट्रिगर करता है.
- अगर खींचकर छोड़े गए डेटा को व्यू में छोड़ा जाता है और - OnReceiveContentListenerकिसी कॉन्टेंट का इस्तेमाल करता है, तो यह फ़ंक्शन 'सही' दिखाता है.
खास तौर पर अपने ऐप्लिकेशन के लिए डेटा मैनेज करने के लिए, OnReceiveContentListener तय करें. एपीआई लेवल 24 तक के साथ काम करने के लिए, OnReceiveContentListener के Jetpack वर्शन का इस्तेमाल करें.
आपके पास View ऑब्जेक्ट के लिए, ड्रैग इवेंट लिसनर और कॉलबैक तरीका हो सकता है. ऐसे में, सिस्टम पहले लिसनर को कॉल करता है. सिस्टम, कॉलबैक मेथड को तब तक कॉल नहीं करता, जब तक कि लिसनर false नहीं दिखाता.
onDragEvent() तरीके और View.OnDragListener का कॉम्बिनेशन, टच इवेंट के साथ इस्तेमाल किए जाने वाले onTouchEvent() और View.OnTouchListener के कॉम्बिनेशन जैसा ही है.
 
  