2012-10-22 30 views
14

में इंडेक्सपाथ में धीमी स्क्रॉलिंग बनाना मैं एक प्रोजेक्ट पर काम कर रहा हूं जहां मैं 'छवि टिकर' बनाने के लिए एक यूआईसीओलेक्शन व्यू का उपयोग कर रहा हूं जहां मैं लोगो की एक श्रृंखला का विज्ञापन कर रहा हूं। संग्रह दृश्य एक आइटम उच्च और बारह आइटम लंबा है, और एक समय में दो से तीन आइटम दिखाता है (दिखाई देने वाले लोगो के आकार के आधार पर)।UICollectionView

मैं पहले आइटम से अंतिम धीमी स्वचालित स्क्रॉलिंग एनीमेशन बनाना चाहता हूं, और फिर दोहराना चाहता हूं।

क्या कोई यह काम करने में सक्षम है? मैं

[myCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:(myImages.count -1) inSection:0] atScrollPosition:UICollectionViewScrollPositionRight animated:YES]; 

का उपयोग कर स्क्रॉलिंग काम कर सकता हूं लेकिन यह बहुत तेज़ तरीका है!

[UIView animateWithDuration:10 delay:2 options:(UIViewAnimationOptionAutoreverse + UIViewAnimationOptionRepeat) animations:^{ 
    [myCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:(myImages.count -1) inSection:0] atScrollPosition:UICollectionViewScrollPositionRight animated:NO]; 
} completion:nil]; 

यह वांछित स्क्रॉलिंग गति पैदावार है, लेकिन केवल पिछले कुछ कोशिकाओं श्रृंखला में दिखाई दे रहे हैं। मुझे संदेह है कि वे (और यहां तक ​​कि प्रारंभिक दृश्य कोशिकाओं) तुरंत हटाए जा रहे हैं।

किसी भी विचार?

+0

मैंने आपके कोड की कोशिश की, वास्तव में यह चीज़ स्क्रॉल है IItemAtIndexPath आपको विशेष इंडेक्स पर ले जाती है, आप यानी [myImages.count -1] पास कर रहे हैं, इसलिए उस इंडेक्स पर छवि –

उत्तर

14

आप इस तरीके का प्रयास कर सकते हैं:

@property (nonatomic, assign) CGPoint scrollingPoint, endPoint; 
@property (nonatomic, strong) NSTimer *scrollingTimer; 
@synthesize scrollingPoint, endPoint; 
@synthesize scrollingTimer; 

- (void)scrollSlowly { 
    // Set the point where the scrolling stops. 
    self.endPoint = CGPointMake(0, 300); 
    // Assuming that you are starting at {0, 0} and scrolling along the x-axis. 
    self.scrollingPoint = CGPointMake(0, 0); 
    // Change the timer interval for speed regulation. 
    self.scrollingTimer = [NSTimer scheduledTimerWithTimeInterval:0.015 target:self selector:@selector(scrollSlowlyToPoint) userInfo:nil repeats:YES]; 
} 

- (void)scrollSlowlyToPoint { 
    self.collectionView.contentOffset = self.scrollingPoint; 
    // Here you have to respond to user interactions or else the scrolling will not stop until it reaches the endPoint. 
    if (CGPointEqualToPoint(self.scrollingPoint, self.endPoint)) { 
     [self.scrollingTimer invalidate]; 
    } 
    // Going one pixel to the right. 
    self.scrollingPoint = CGPointMake(self.scrollingPoint.x, self.scrollingPoint.y+1); 
} 
+1

दिखाई दे रही है, यदि आपके पास कोई यूआई थ्रेड ब्लॉक है, तो आपके पास अन्य नियंत्रण जिनके लिए फोकस परिवर्तन की आवश्यकता होती है (जैसे टीवीओएस में) यह काम नहीं करता है। – puru020

10

मैं एक "1 पिक्सेल ऑफसेट" चाल का उपयोग करें। प्रोग्रामेटिक रूप से स्क्रॉल करते समय, बस contentOffset.x से 1 पिक्सेल को जितना चाहिए उससे कम/कम सेट करें। यह अनजान होना चाहिए। और समापन ब्लॉक में इसे वास्तविक मूल्य पर सेट करें। इस तरह आप समय से पहले सेल dequeuing समस्या से बचने और आसान स्क्रॉलिंग एनीमेशन प्राप्त कर सकते हैं;)

यहाँ (पेज 1 से उदा 2 करने के लिए) को सही पृष्ठ पर स्क्रॉल का एक उदाहरण है। ध्यान दें कि animations: ब्लॉक में मैं वास्तव में एक पिक्सेल कम (pageWidth * nextPage - 1) स्क्रॉल करता हूं। मैं फिर completion: ब्लॉक में सही मान बहाल करता हूं।

CGFloat pageWidth = self.collectionView.frame.size.width; 
int currentPage = self.collectionView.contentOffset.x/pageWidth; 
int nextPage = currentPage + 1; 

[UIView animateWithDuration:1 
         delay:0 
        options:UIViewAnimationOptionCurveEaseOut 
       animations:^{ 
        [self.collectionView setContentOffset:CGPointMake(pageWidth * nextPage - 1, 0)]; 
       } completion:^(BOOL finished) { 
        [self.collectionView setContentOffset:CGPointMake(pageWidth * nextPage, 0)]; 
       }]; 
+3

बिना किसी कारण टिप्पणी के मतदान नीचे कोई अच्छा नहीं करता है, आपको पता है? – Hlung

+0

पेजविड्थ और अगली पेज उत्तर के संदर्भ में परिभाषित नहीं हैं – Sneakyness

+1

@ स्नीकीनेस ने उनको जोड़ा। धन्यवाद! – Hlung

0

ज फ़ाइल में घोषित इस टाइमर,

NSTimer *Timer; 

प्लेस इस टाइमर कोड,

[CollectionView reloadData]; 
    Timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(AutoScroll) userInfo:nil repeats:YES]; 
तो

,

#pragma mark- Auto scroll image collectionview 
-(void)AutoScroll 
{ 
    if (i<[Array count]) 
    { 
     NSIndexPath *IndexPath = [NSIndexPath indexPathForRow:i inSection:0]; 
     [self.ImageCollectionView scrollToItemAtIndexPath:IndexPath 
      atScrollPosition:UICollectionViewScrollPositionRight animated:NO]; 
     i++; 
     if (i==[Array count]) 
     { 
      i=0; 
     } 
    } 
} 

आशा है कि यह हो जाएगा उपयोगी।

3

किसी और को ढूंढने के लिए, मैंने स्विफ्ट पर काम करने के लिए मासा के सुझाव को अपडेट किया है और मैंने अंत में थोड़ा सा आसान शुरुआत की है, इसलिए यह मूल स्क्रॉल ITemsToIndexPath एनिमेटेड कॉल की तरह काम करता है। मेरे पास मेरे दृश्य में सैकड़ों आइटम हैं इसलिए एक स्थिर गति मेरे लिए एक विकल्प नहीं थी।

var scrollPoint: CGPoint? 
var endPoint: CGPoint? 
var scrollTimer: NSTimer? 
var scrollingUp = false 

func scrollToIndexPath(path: NSIndexPath) { 
    let atts = self.collectionView!.layoutAttributesForItemAtIndexPath(path) 
    self.endPoint = CGPointMake(0, atts!.frame.origin.y - self.collectionView!.contentInset.top) 
    self.scrollPoint = self.collectionView!.contentOffset 
    self.scrollingUp = self.collectionView!.contentOffset.y > self.endPoint!.y 

    self.scrollTimer?.invalidate() 
    self.scrollTimer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "scrollTimerTriggered:", userInfo: nil, repeats: true) 
} 

func scrollTimerTriggered(timer: NSTimer) { 
    let dif = fabs(self.scrollPoint!.y - self.endPoint!.y)/1000.0 
    let modifier: CGFloat = self.scrollingUp ? -30 : 30 

    self.scrollPoint = CGPointMake(self.scrollPoint!.x, self.scrollPoint!.y + (modifier * dif)) 
    self.collectionView?.contentOffset = self.scrollPoint! 

    if self.scrollingUp && self.collectionView!.contentOffset.y <= self.endPoint!.y { 
     self.collectionView!.contentOffset = self.endPoint! 
     timer.invalidate() 
    } else if !self.scrollingUp && self.collectionView!.contentOffset.y >= self.endPoint!.y { 
     self.collectionView!.contentOffset = self.endPoint! 
     timer.invalidate() 
    } 
} 

अंतर और संशोधक के मानों को ट्वीक करना अधिकांश स्थितियों के लिए आसानी/अवधि का स्तर समायोजित करता है।

+0

बहुत अच्छा काम करता है और यूआई थ्रेड को अवरुद्ध नहीं करता है। धन्यवाद – Gmeister4

7

तुम भी indexpath से indexpath करने के लिए "कूद" बिना एक "धीमी" आप UICollectionView के अंत करने के लिए स्क्रॉल हो सकता था।मैं एक TVOS एप्लिकेशन पर एक संग्रह को देखने के लिए जल्दी से इस बनाया:

func autoScroll() { 
    let co = collectionView.contentOffset.x 
    let no = co + 1 

    UIView.animateWithDuration(0.001, delay: 0, options: .CurveEaseInOut, animations: { [weak self]() -> Void in 
     self?.collectionView.contentOffset = CGPoint(x: no, y: 0) 
     }) { [weak self](finished) -> Void in 
      self?.autoScroll() 
    } 
} 

मैं सिर्फ viewDidLoad() में autoScroll() फोन और बाकी अपने आप में यह ख्याल रखते हैं। स्क्रॉलिंग की गति UIView के एनीमेशन समय द्वारा तय की जाती है। आप (मैंने कोशिश नहीं की है) 0 सेकंड के साथ एक एनएसटीमर जोड़ें, ताकि आप इसे usercroll पर अमान्य कर सकें।

+0

मैं भी इसी तरह की कोशिश करने की कोशिश कर रहा हूं, लेकिन एक अनंत लूप बनाना चाहता हूं (आखिरी के बाद पहली बार जा रहा हूं)। आपने ऐसा कैसे किया? – puru020

+0

@ puru020 मुझे यह समस्या भी है। यदि आपके पास समान आकार की वस्तुओं के साथ संग्रहदृश्य है, तो यह आसान हो सकता है। मूल रूप से आप जो करते हैं वह है कि आप संग्रहदृश्य आइटम के अंत में पहले कुछ आइटम जोड़ते हैं, और शुरुआत में आइटम की अंतिम श्रेणी को जोड़ते हैं। जब अंतिम आइटम स्क्रीन पर आ रहे हैं तो आप उपयोगकर्ता को ध्यान दिए बिना 'UICollectionView' की शुरुआत में' ContentOffset' को स्थानांतरित कर सकते हैं; इसलिए: अनंत स्क्रॉल। इससे मदद मिल सकती है: http://stackoverflow.com/questions/15549233/view-with-continuous-scroll-both-horizontal-and-vertical –

+0

@PaulPeelen आपको स्विफ्ट UIView ब्लॉक में कैप्चर सूची सेट करने की आवश्यकता नहीं है क्योंकि इसे निष्पादित किया गया है बाद के चरण में। यह एक बनाए रखने चक्र नहीं बनाएगा। –