डिस्क्लेमर: मुख्यतः रिएक्ट नेटिव 0.50 में मेरे अपने प्रयोग का परिणाम है। ScrollViewप्रलेखन वर्तमान में नीचे कवर जानकारी का एक बहुत याद आ रही है; उदाहरण के onScrollEndDragलिए पूरी तरह से undocumented है। चूंकि यहां सब कुछ अनिर्धारित व्यवहार पर निर्भर करता है, मैं दुर्भाग्य से कोई वादा नहीं कर सकता कि यह जानकारी एक साल या अब से एक महीने भी सही रहेगी।
इसके अलावा, नीचे दी गई हर चीज एक विशुद्ध रूप से वर्टिकल स्क्रॉलव्यू मानती है, जिसकी y ऑफसेट हम में रुचि रखते हैं; यदि जरूरत हो तो एक्स ऑफ़सेट्स में अनुवाद करना , उम्मीद है कि पाठक के लिए एक आसान व्यायाम होगा।
एक ScrollViewले पर विभिन्न घटना संचालकों eventऔर आप के माध्यम से वर्तमान स्क्रॉल स्थिति प्राप्त करते हैं event.nativeEvent.contentOffset.y। इनमें से कुछ हैंडलर Android और iOS के बीच थोड़ा अलग व्यवहार करते हैं, जैसा कि नीचे विस्तृत है।
Android पर
जब उपयोगकर्ता स्क्रॉल कर रहा होता है, तब हर फ्रेम पर आग लग जाती है, जबकि स्क्रॉल दृश्य को उपयोगकर्ता द्वारा जारी किए जाने के बाद स्क्रॉल दृश्य ग्लाइड होता है, जब स्क्रॉल दृश्य आराम करने के लिए आता है, और जब भी स्क्रॉल का ऑफसेट इसके फ्रेम के परिणामस्वरूप बदलता है। बदलते (उदाहरण के लिए परिदृश्य से चित्र के रोटेशन के कारण)।
IOS पर
जब उपयोगकर्ता घसीट रहा हो या जब स्क्रॉल दृश्य ग्लाइडिंग कर रहा हो, तब कुछ आवृत्ति scrollEventThrottleपर और जब फ्रेम प्रति बार एक बार निर्धारित किया जाता है scrollEventThrottle={16}। यदि उपयोगकर्ता स्क्रॉल करने के लिए स्क्रॉल दृश्य जारी करता है, जबकि इसे विभाजित करने के लिए पर्याप्त गति है, तो onScrollग्लाइडिंग के बाद आराम करने के लिए हैंडलर भी आग लगाएगा। हालांकि, उपयोगकर्ता खींच लेता है और उसके बाद पुस्तक दृश्य विज्ञप्ति जबकि यह स्थिर है, onScrollहै न आग में अंतिम स्थान के लिए जब तक इसकी गारंटी scrollEventThrottleऐसी निर्धारित किया गया है कि onScrollआग स्क्रॉल के हर फ्रेम।
सेटिंग के लिए एक प्रदर्शन लागत है scrollEventThrottle={16}जिसे बड़ी संख्या में सेट करके कम किया जा सकता है। हालांकि, इसका मतलब है कि onScrollहर फ्रेम में आग नहीं लगेगी।
जब ग्लाइडिंग के बाद स्क्रॉल दृश्य रुक जाता है तो आग लग जाती है। अगर उपयोगकर्ता स्क्रॉल दृश्य को स्थिर करता है तो यह बिल्कुल भी आग नहीं लगाता है, क्योंकि यह स्थिर नहीं है।
onScrollEndDrag
जब उपयोगकर्ता स्क्रॉल दृश्य को खींचना बंद कर देता है, तो यह ध्यान दिए बिना कि स्क्रॉल दृश्य स्थिर रहता है या सरकना शुरू होता है।
व्यवहार में इन अंतरों को देखते हुए, ऑफसेट का ट्रैक रखने का सबसे अच्छा तरीका आपके सटीक परिस्थितियों पर निर्भर करता है। सबसे जटिल मामले में (आपको एंड्रॉइड और आईओएस का समर्थन करने की आवश्यकता है, जिसमें ScrollViewरोटेशन के कारण फ्रेम में परिवर्तन को संभालना शामिल है , और आप एंड्रॉइड पर scrollEventThrottle16 से सेटिंग पर प्रदर्शन जुर्माना स्वीकार नहीं करना चाहते हैं ), और आपको संभालने की आवश्यकता है स्क्रॉल दृश्य में भी सामग्री में परिवर्तन , तो यह एक सही लानत गड़बड़ है।
सबसे सरल मामला है, अगर आपको केवल एंड्रॉइड को संभालने की आवश्यकता है; बस उपयोग करें onScroll:
<ScrollView
onScroll={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
>
अतिरिक्त रूप से iOS का समर्थन करने के लिए, यदि आप onScrollहैंडलर को हर फ्रेम में फायर करते हैं और उस के प्रदर्शन निहितार्थ को स्वीकार करते हैं, और यदि आपको फ़्रेम परिवर्तन को संभालने की आवश्यकता नहीं है, तो यह केवल थोड़ा अधिक जटिल है:
<ScrollView
onScroll={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
scrollEventThrottle={16}
>
IOS पर प्रदर्शन ओवरहेड को कम करने के लिए अभी भी गारंटी देते हुए कि हम किसी भी स्थिति को रिकॉर्ड करते हैं, जिस पर स्क्रॉल दृश्य निपटता है, हम बढ़ा सकते हैं scrollEventThrottleऔर इसके अलावा एक onScrollEndDragहैंडलर प्रदान कर सकते हैं :
<ScrollView
onScroll={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
onScrollEndDrag={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
scrollEventThrottle={160}
>
लेकिन अगर हम फ्रेम में बदलाव करना चाहते हैं (उदाहरण के लिए, क्योंकि हम डिवाइस को घुमाने की अनुमति देते हैं, स्क्रॉल दृश्य के फ्रेम के लिए उपलब्ध ऊंचाई बदलकर) और / या सामग्री में परिवर्तन होता है, तो हमें अतिरिक्त रूप से दोनों को लागू करना होगा onContentSizeChangeऔर दोनों onLayoutकी ऊंचाई का ट्रैक रखना होगा। स्क्रॉल दृश्य के फ्रेम और उसकी सामग्री, और इस तरह लगातार अधिकतम संभव ऑफसेट और अनुमान लगाता है जब ऑफसेट स्वचालित रूप से एक फ्रेम या सामग्री आकार परिवर्तन के कारण कम हो गया है:
<ScrollView
onLayout={event => {
this.frameHeight = event.nativeEvent.layout.height;
const maxOffset = this.contentHeight - this.frameHeight;
if (maxOffset < this.yOffset) {
this.yOffset = maxOffset;
}
}}
onContentSizeChange={(contentWidth, contentHeight) => {
this.contentHeight = contentHeight;
const maxOffset = this.contentHeight - this.frameHeight;
if (maxOffset < this.yOffset) {
this.yOffset = maxOffset;
}
}}
onScroll={event => {
this.yOffset = event.nativeEvent.contentOffset.y;
}}
onScrollEndDrag={event => {
this.yOffset = event.nativeEvent.contentOffset.y;
}}
scrollEventThrottle={160}
>
हाँ, यह बहुत भयानक है। मैं भी 100% निश्चित नहीं हूं कि यह हमेशा उन मामलों में सही काम करेगा जहां आप एक साथ स्क्रॉल दृश्य के फ्रेम और सामग्री दोनों का आकार बदलते हैं। लेकिन यह सबसे अच्छा है जिसके साथ मैं आ सकता हूं, और जब तक यह सुविधा ढांचे के भीतर नहीं जुड़ जाती , मुझे लगता है कि यह सबसे अच्छा है जो कोई भी कर सकता है।