मैं प्रोग्रामेटिक रूप से UIScrollView में स्क्रॉलिंग को कैसे रोक सकता हूं?


81

नोट: यहाँ दिया गया उत्तर मेरे लिए कारगर नहीं है।

मेरे पास एक UIScrollView है (तालिका दृश्य नहीं है, बस एक कस्टम चीज़ है), और जब उपयोगकर्ता कुछ कार्य करता है, तो मैं दृश्य के अंदर किसी भी स्क्रॉलिंग (खींचने या मंदी) को मारना चाहता हूं। मैंने यह करने की कोशिश की है:

[scrollView scrollRectToVisible:CGRectInset([scrollView bounds], 10, 10) animated:NO];

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

धन्यवाद।

जवाबों:


108

मैं आपके मूल समाधान के साथ थोड़ा खेला, और यह ठीक काम करने लगता है। मुझे लगता है कि आपके पास लगभग यह था, लेकिन आप बस उस रूट को ऑफसेट कर रहे थे जो आपने बहुत अधिक उपयोग किया था, और यह भूल गए कि आप मूल रूट पर सीधे वापस स्क्रॉल कर सकते हैं।

किसी भी स्क्रॉल कार्रवाई के लिए सामान्यीकृत समाधान यह है:

- (void)killScroll 
{
    CGPoint offset = scrollView.contentOffset;
    offset.x -= 1.0;
    offset.y -= 1.0;
    [scrollView setContentOffset:offset animated:NO];
    offset.x += 1.0;
    offset.y += 1.0;
    [scrollView setContentOffset:offset animated:NO];
}

[संपादित करें] आईओएस 4.3 (और संभवतः पहले) के रूप में यह भी काम करता दिखाई देता है

- (void)killScroll 
{
    CGPoint offset = scrollView.contentOffset;
    [scrollView setContentOffset:offset animated:NO];
}

1
डेविड: महान, धन्यवाद। मैंने अपने आप को इस दिशा में मोड़ दिया था, लेकिन स्क्रॉल घाव के ठीक बाहर 1x1 रेक्ट को चुनने के बारे में कम तुच्छ गणना के साथ समाप्त हुआ। ऑफसेट करने के अपने सुझाव को लेना और फिर तुरंत बहाल करना (जो एक अप्रकाशित व्यवहार का लाभ उठाने के लिए स्पष्ट रूप से लगता है जहां एक घटना में क्रमिक कॉल वास्तव में काम करते हैं भले ही "परिणाम" एक न-ऑप हो), यह ठीक काम करता है। मैं सामान्यीकृत समाधान को शामिल करने के लिए आपके उत्तर को ऊपर संपादित करने जा रहा हूं जो किसी भी स्क्रॉल दिशा के लिए काम करना चाहिए। धन्यवाद!
बेन ज़ोट्टो

(आशा है कि आप संपादन को बुरा नहीं मानते, बाद के यात्रियों के लिए स्पष्ट करना चाहते थे। आपके उत्तर के लिए धन्यवाद!)
बेन ज़ोट्टो

बहुत अच्छा लग रहा है ... वैसे आप कैसे हैं जहाँ आप थे? क्या आप इसे मारने से पहले ऑफसेट को बचाते हैं, और फिर वहां वापस आते हैं?
लोर फ्रेनकेल

2
IOS 7 में, जब स्क्रॉलव्यू डिलीवर हो रहा है, केवल शीर्ष समाधान काम करता है (+ = 1, - = 1 समाधान)।
साहिल

1
इस समाधान में सुधार किया जा सकता है। + = 1 के बजाय + = 0.1 का उपयोग करें, इसलिए की एकल कॉल setContentOffsetपर्याप्त होगी। स्क्रॉल दृश्य सामग्री ऑफसेट को स्वचालित रूप से गोल करेगा।
kelin

91

सामान्य जवाब है कि, है [scrollView setContentOffset:offset animated:NO]है ही नहीं के रूप में [scrollView setContentOffset:offset]!

  • [scrollView setContentOffset:offset animated:NO] वास्तव में किसी भी चल रहे एनीमेशन को रोकता है।
  • [scrollView setContentOffset:offset] किसी भी चल रहे एनीमेशन को बंद नहीं करता है।
  • उसी के लिए scrollView.contentOffset = offset: किसी भी चल रहे एनीमेशन को नहीं रोकता है।

यह कहीं भी प्रलेखित नहीं है, लेकिन यह व्यवहार जैसा कि iOS 6.1 और iOS 7.1 पर परीक्षण किया गया है - शायद पहले भी था।

तो चल रहे एनीमेशन / मंदी को रोकने के लिए समाधान इस प्रकार सरल है:

[scrollView setContentOffset:scrollView.contentOffset animated:NO];

मूल रूप से डेविड लियू ने अपने संपादित जवाब में क्या कहा। लेकिन मैं स्पष्ट करना चाहता था, कि ये दोनों एपीआई समान नहीं हैं ।

स्विफ्ट 3:

scrollView.setContentOffset(scrollView.contentOffset, animated:false)

11
हमारे बीच "कारण चाहने वालों" के स्पष्टीकरण पर अच्छा किया ... (:
एविल सकल

3
यह थोथा मुझे हालांकि दुखी करता है।
DCMaxxx

2
मुझे समझ में नहीं आता है कि यह सामान क्यों नहीं प्रलेखित किया गया है ... अत्यावश्यक
user1105951

इससे भी अधिक दिलचस्प (कम से कम) iOS 11.3 और 11.4 में है: यदि सामग्रीऑफसेट को उदाहरण के लिए एनिमेटेड (300, 0) पर ले जाया जाता है, तो "contentOffset = (300, 0)" को असाइन किया जाता है, जबकि एनीमेशन अभी भी चलता है, कंटेंटऑसेटसेट रीसेट हो सकता है (०, ०)! यह एक बग होना चाहिए!
जनवरी

68

मेरे लिए, डेविड लुई का उपरोक्त उत्तर मेरे लिए कारगर नहीं था। यह वही है जो मैंने किया है:

- (void)killScroll {
    self.scrollView.scrollEnabled = NO;
    self.scrollView.scrollEnabled = YES;
}

इसके लायक क्या है, मैं iOS 6.0 iPhone सिम्युलेटर का उपयोग कर रहा हूं।


2
+1 जैसा आपने कहा, दूसरे ने मेरे लिए भी काम नहीं किया, लेकिन इस समाधान ने बहुत काम किया!
ब्रेनजेट

1
बहुत बढ़िया, यह supportedInterfaceOrientationsस्क्रॉल घटनाओं को रोकने के लिए पूरी तरह से काम करता है यदि उपयोगकर्ता स्क्रॉल करते समय डिवाइस को घुमा रहा है , जो कभी-कभी एक गड़बड़ है जो आप कर रहे हैं उसके आधार पर।
cprcrack

21

यह मैं अपने स्क्रॉल विचारों और अन्य सभी संबंधित उपवर्गों के लिए करता हूं:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
 {
    *targetContentOffset = scrollView.contentOffset;
 }

यह वर्तमान में ऑफसेट targetContentOffsetकरने के लिए सेट है scrollView, इस प्रकार स्क्रॉल को रोकने के लिए क्योंकि यह लक्ष्य तक पहुँच गया है। यह वास्तव में एक ऐसी विधि का उपयोग करने के लिए समझ में आता है जिसका उद्देश्य यह है कि उपयोगकर्ता लक्षित कर सकते हैं contentOffset

तीव्र

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    targetContentOffset.pointee = scrollView.contentOffset
}

यह ऐप्पल माना जाता है कि डेवलपर्स का उपयोग करना है। क्योंकि सभी अन्य किसी न किसी बिंदु पर कीड़े होते हैं। मुझे आश्चर्य है कि यह स्वीकृत उत्तर नहीं है।
ओलडोर

यह इस प्रतिनिधि विधि के लिए है। बहुत बढ़िया जवाब।
रयान

मेरी राय में यह सबसे सुरुचिपूर्ण समाधान है जैसा कि Apple अपने दस्तावेज़ में कहता है: "आपके एप्लिकेशन को समायोजित करने के लिए targetContentOffset पैरामीटर का मान बदल सकता है जहां स्क्रॉलव्यू अपने स्क्रॉलिंग एनीमेशन को समाप्त करता है।" मेरे लिए बहुत अच्छा काम किया
Macistador

यह सही जवाब है। उपर्युक्त में से किसी ने भी मेरे लिए काम नहीं किया
सेतु

20

स्क्रोल को स्विफ्ट में बंद करें :

scrollView.setContentOffset(scrollView.contentOffset, animated: false)

16

वास्तव में ... सबसे "आधुनिक" तरीका होगा ->

scrollview.panGestureRecognizer.enabled = false;
scrollview.panGestureRecognizer.enabled = true;

यह इशारा-पहचानकर्ता को निष्क्रिय कर देता है जो सिर्फ एक पल के लिए स्क्रॉल करने के लिए जिम्मेदार है जो वर्तमान स्पर्श को मार देगा। उपयोगकर्ता को उंगली उठाने और इसे फिर से स्क्रॉल करना शुरू करने के लिए नीचे रखना होगा।

संपादित करें: यह वास्तव में उपयोगकर्ता के वर्तमान ड्रैगिंग को मारता है लेकिन अगर इस स्थिति में स्क्रॉलव्यू वर्तमान में है तो तुरंत मंदी को रोक नहीं सकता है। ऐसा करने के लिए स्वीकृत उत्तरों को संपादित करना बहुत अच्छा तरीका है xD

[scrollview setContentOffset: scrollview.contentOffset animated:false];

वैसे मैं इसका उपयोग एक ऐप में करता हूं और यह वही करता है जो ओपी द्वारा पूछा जाता है। क्या आप कृपया थोड़ा और संदर्भ दे सकते हैं? क्या काम नहीं कर रहा है या क्यों?
Xatian

ओह सॉरी ... मुझे लगता है कि मुझे पता है ... मैंने बस उस प्रश्न के भाग का उत्तर दिया जिसकी मुझे तलाश थी ... दूसरे भाग की मैंने अनदेखी की ... :-) -> संपादित किया।
Xatian

मंदी को रोकता नहीं है।
रुडोल्फ एडमकोविक्स

5

सबसे साफ तरीका UIScrollView को उपवर्गित करेगा और आपकी स्वयं की SetContentOffset विधि प्रदान करेगा। यह, पर संदेश देना चाहिए केवल अगर आप अपने चालू नहीं है freezeबूलियन संपत्ति।

इस तरह:

BOOL freeze; // and the @property, @synthesize lines..

-(void)setContentOffset:(CGPoint)offset
{
    if ( !freeze ) [super setContentOffset:offset];
}

फिर, जमने के लिए:

scrollView.freeze = YES;

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

ठीक है, इस तरह के मुद्दे पूर्व अनुभव से परिचित लगते हैं ... क्यों decelerationRate = 1e10;फ्रीज == हाँ, जबकि सेटिंग से मंदी नहीं ?
mvds

(आंतरिक गणित को नहीं जानते हुए, 10 * UIScrollViewDecelerationRateFast 1e10 से अधिक समझदार विकल्प हो सकता है)
mvds

दिलचस्प विचार! दुर्भाग्यवश यह मान दबाना प्रतीत होता है। कोशिश की, और वहाँ इस का एक मूल्य है जो तुरंत बंद करने के लिए मंदी का कारण होगा प्रतीत नहीं होता है। सबसे अच्छा मैं यह कर सकता हूँ कि यह सुस्त है। :)
बेन ज़ोटो

प्लान बी को एक संक्षिप्त अवधि के लिए स्क्रॉलिंग को अक्षम करना है - शायद आप इससे दूर हो सकते हैं, क्योंकि आप सेटकोन्टऑफसेट को वैसे भी अवरुद्ध कर रहे हैं, उम्मीद है कि स्क्रॉलिंग को अक्षम करने से होने वाले दुष्प्रभावों को रोका जा सके।
mvds


3

केवल उपयोगकर्ता सहभागिता स्क्रॉल करें अक्षम करें। (स्विफ्ट)

scrollView.isScrollEnabled = false

स्क्रॉल करने के दौरान स्क्रॉल एनीमेशन के दौरान अक्षम करें। (स्विफ्ट)

var scrollingByVelocity = false

func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
    if !scrollingByVelocity {
        scrollView.setContentOffset(scrollView.contentOffset, animated: false)
    }
}

0

मैंने इस तरीके की कोशिश की है:

self.collectionView.collectionViewLayout.finalizeCollectionViewUpdates()


0

यह मेरे लिए स्विफ्ट 4.2 में काम करता है :

   func killScroll() {
    self.scrollView.isScrollEnabled = false;
    self.scrollView.isScrollEnabled = true;
}

... एक विस्तार के रूप में:

extension UIScrollView {
    func killScroll() {
        self.isScrollEnabled = false;
        self.isScrollEnabled = true;

    }
}

0

मैं स्क्रॉलिंग को केवल तभी अक्षम करना चाहता था जब स्क्रॉल के भीतर एक निश्चित UIView स्वाइप के दौरान स्पर्श का स्रोत हो। हमें UIScrollView के बाहर UIView को स्थानांतरित करने के लिए काफी रिफैक्टिंग की आवश्यकता होगी, क्योंकि हमारे पास एक जटिल दृश्य पदानुक्रम था।

वर्कअराउंड के रूप में, मैंने सबव्यू में एक एकल UIPanGestureRecognizer जोड़ा जिसमें मैं स्क्रॉल करने से रोकना चाहता था। यह UIPanGestureRecognizer cancelsTouchesInViewUIScrollView के पैनग्रेस्चर को सक्रिय होने से रोकता है।

यह एक 'हैक' का एक छोटा सा है, लेकिन यह एक सुपर आसान बदलाव है, और यदि आप एक XIB या स्टोरीबोर्ड का उपयोग कर रहे हैं, तो आपको बस सवाल में उप-इशारे पर पैन जेस्चर को खींचने की आवश्यकता है।


0

स्विफ्ट 5+

एक्सटेंशन का उपयोग करके

extension UIScrollView  {
    
    func stopDecelerating() {
        let contentOffset = self.contentOffset
        self.setContentOffset(contentOffset, animated: false)
    }
}

उपयोग

    myScrollView.stopDecelerating()
    // your stuff
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.