2011-05-17 18 views
7

को कम करने पर नियंत्रण करने के लिए स्नैप करें UIScrollView में प्रोग्रामर के लिए बहुत सारी जानकारी उपलब्ध है, लेकिन मुझे उस स्थान को नियंत्रित करने का एक स्पष्ट तरीका नहीं दिख रहा है जो स्क्रॉल जेस्चर से कम होने के बाद नियंत्रण रोकता है।UIScrollView -

असल में मैं स्क्रॉलव्यू स्क्रीन के विशिष्ट क्षेत्रों में स्नैप करना चाहता हूं। उपयोगकर्ता अभी भी सामान्य की तरह स्क्रॉल कर सकता है, लेकिन जब वे स्क्रॉलिंग को रोकते हैं तो दृश्य को सबसे प्रासंगिक स्थान पर स्नैप करना चाहिए, और झटका इशारा के मामले में इन स्थानों पर मंदी को भी रोकना चाहिए।

क्या ऐसा कुछ करने का कोई आसान तरीका है, या क्या मुझे कस्टम स्क्रॉलिंग नियंत्रण लिखने के लिए इस प्रभाव को पूरा करने का एकमात्र तरीका माना जाना चाहिए?

उत्तर

7

scrollViewDidEndDecelerating: और scrollViewDidEndDragging:willDecelerate: (पिछले एक बस जब उनकी गति जाएगा पैरामीटर NO है) के बाद आप अपने UIScrollView इच्छित स्थान पर की contentOffset पैरामीटर स्थापित करना चाहिए।

आप भी अपने scrollview की contentOffset संपत्ति की जाँच करके वर्तमान स्थिति पता चल जाएगा, और फिर निकटतम वांछित क्षेत्र आप

है कि हालांकि आप अपने खुद के स्क्रॉल नियंत्रण बनाने की जरूरत नहीं है की गणना, आप होगा वांछित पदों पर मैन्युअल रूप से स्क्रॉल करने के लिए

7

फ़ेलिप ने जो कहा, उसे जोड़ने के लिए, मैंने हाल ही में एक तालिका दृश्य बनाया है जो यूआईपीकर द्वारा समान रूप से कोशिकाओं को स्नैप करता है। एक चालाक स्क्रॉलव्यू प्रतिनिधि निश्चित रूप से ऐसा करने का तरीका है (और आप इसे एक यूटिव्यूव्यूव पर भी कर सकते हैं, क्योंकि यह केवल यूस्क्रोलव्यू का उप-वर्ग है)।

स्क्रॉल दृश्य को कम करने के बाद मैंने स्क्रॉल व्यू को शुरू करने के बाद यह किया था (यानी स्क्रॉल व्यूडिड एंड ड्रैगिंग: विल डिस्सेरेट: जिसे कॉल किया जाता है), scrollViewDidScroll का जवाब देना और पिछले स्क्रॉल ईवेंट के साथ diff की गणना करना।

जब diff की तुलना में एक 2 पिक्सल के 5 कहता हूं, मैं निकटतम सेल के लिए चेक करें, फिर जब तक प्रतीक्षा करें कि सेल में कुछ पिक्सल द्वारा पारित किया गया है, तो setContentOffset साथ दूसरी दिशा में वापस स्क्रॉल कम है: एनिमेटेड: । यह थोड़ा बाउंस प्रभाव बनाता है जो उपयोगकर्ता अनुभव के लिए बहुत अच्छा है, क्योंकि यह स्नैपिंग पर एक अच्छी प्रतिक्रिया देता है।

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

मैंने सेटकंटेंट ऑफसेट को कॉल करने के लिए बेवकूफ दृष्टिकोण की भी कोशिश की है: एनिमेटेड: स्क्रॉलव्यूडिड एंड डिस्सेलरेटिंग पर: लेकिन यह वास्तव में अजीब एनीमेशन बनाता है (या अगर आप एनिमेट नहीं करते हैं तो केवल सादा भ्रमित कूद), जो कमजोर पड़ने की दर को कम करता है है (आप एक धीमी गति से एक तेजी से कूदने के लिए कूद जाएगा)।

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

+0

धन्यवाद @kra, यह निश्चित रूप से एक आसान एनीमेशन बनाता है और स्क्रॉलव्यू अधिक प्राकृतिक लगता है! –

27

के बाद से UITableView एक UIScrollView उपवर्ग है, तो आप UIScrollViewDelegate विधि को लागू कर सकते हैं:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView 
    withVelocity:(CGPoint)velocity 
    targetContentOffset:(inout CGPoint *)targetContentOffset 

और फिर गणना क्या निकटतम वांछित लक्ष्य सामग्री ऑफसेट जो आप चाहते है, और सेट कि inout CGPoint पैरामीटर पर।

मैंने अभी कोशिश की है और यह अच्छी तरह से काम करता है।

पहले, unguided इस तरह ऑफसेट पुनः प्राप्त:

CGFloat unguidedOffsetY = targetContentOffset->y; 

फिर, कुछ गणित, जहां आप इसे होना चाहेंगे के माध्यम से पता लगाएं तालिका शीर्ष लेख की ऊंचाई टिप्पण। यहाँ मेरी कोड में एक नमूना अमेरिकी राज्य का प्रतिनिधित्व करने के लिए कस्टम कोशिकाओं के साथ काम कर रहा है:

CGFloat guidedOffsetY; 

if (unguidedOffsetY > kFirstStateTableViewOffsetHeight) { 
    int remainder = lroundf(unguidedOffsetY) % lroundf(kStateTableCell_Height_Unrotated); 
    log4Debug(@"Remainder: %d", remainder); 
    if (remainder < (kStateTableCell_Height_Unrotated/2)) { 
     guidedOffsetY = unguidedOffsetY - remainder; 
    } 
    else { 
     guidedOffsetY = unguidedOffsetY - remainder + kStateTableCell_Height_Unrotated; 
    } 
} 
else { 
    guidedOffsetY = 0; 
} 

targetContentOffset->y = guidedOffsetY; 

अंतिम पंक्ति ऊपर वास्तव में inout पैरामीटर, जो स्क्रॉल दृश्य बताती है कि यह है में वापस मूल्य लिखते हैं, y- ऑफसेट आप ' इसे पसंद करने के लिए पसंद है।

अंत में, यदि आप एक प्राप्त परिणाम नियंत्रक से निपट रहे हैं, और आप जानना चाहते हैं कि अभी क्या हुआ है, तो आप ऐसा कुछ कर सकते हैं (मेरे उदाहरण में, संपत्ति "राज्य" अमेरिकी राज्यों के लिए एफआरसी है)। मैं उस जानकारी का उपयोग एक बटन शीर्षक सेट करने के:

NSUInteger selectedStateIndexPosition = floorf((guidedOffsetY + kFirstStateTableViewOffsetHeight)/kStateTableCell_Height_Unrotated); 
log4Debug(@"selectedStateIndexPosition: %d", selectedStateIndexPosition); 
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:selectedStateIndexPosition inSection:0]; 
CCState *selectedState = [self.states objectAtIndexPath:indexPath]; 
log4Debug(@"Selected State: %@", selectedState.name); 
self.stateSelectionButton.titleLabel.text = selectedState.name; 

रवाना विषय नोट: आपका अनुमान सही है, "log4Debug" बयान सिर्फ प्रवेश कर रहे हैं। संयोग से, मैं इसके लिए Lumberjack का उपयोग कर रहा हूँ, लेकिन मैं पुराने Log4Cocoa से कमांड वाक्यविन्यास पसंद करते हैं। इस तरह

+0

धन्यवाद! सुपर सहायक – theVurt

+0

स्क्रॉल करने योग्य व्यू कंट्रोलर को दबाते समय सामग्री ऑफसेट UINavigationBar ऊंचाई और मूल में कारक होगा। (यकीन नहीं है कि ऐसा क्यों करता है क्योंकि इसका कोई मतलब नहीं है लेकिन यह वही करता है) – cynistersix

6

कोशिश कुछ:

- (void) snapScroll; 
{ 
    int temp = (theScrollView.contentOffset.x+halfOfASubviewsWidth)/widthOfSubview; 
    theScrollView.contentOffset = CGPointMake(temp*widthOfSubview , 0); 
} 

- (void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate; 
{ 
    if (!decelerate) { 
     [self snapScroll]; 
    } 
} 

- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{ 
    [self snapScroll]; 
} 

इस पोस्ट-दशमलव अंक के पूर्णांक के ड्रॉप का लाभ लेता है। यह भी मान लें कि आपके सभी विचार 0,0 से ऊपर हैं और केवल सामग्री ऑफ़सेट है जो इसे विभिन्न क्षेत्रों में दिखाता है।

नोट: प्रतिनिधि को हुक अप करें और यह पूरी तरह से ठीक काम करता है। आपको एक संशोधित संस्करण मिल रहा है - मेरा वास्तविक वास्तविक स्थिरांक है। मैंने चर का नाम बदल दिया ताकि आप इसे आसानी से पढ़ सकें