The original use of scrollView to achieve infinite rotation, each rotation map is UIImageView, page number, title, with scrollView implementation is relatively simple. But I recently came across a need. There are several heads and buttons on each rote map, which cannot be realized with the rote map implemented by scrollView in the current project, or the changes are relatively large. So I wanted to do collectionView. The initial idea was that each wheel map would be a custom cell, which would be relatively simple. The dataSource is set to a large number, creating n multiple cells, which can be used to reach infinity… According to the truth, not to say how the performance, is set as a relatively large number, in theory, the number is also limited! It’s not an infinite rotation

My general design ideas are as follows:

1. Timer. It is used to scroll A page at A fixed interval. 2, collectionView, A cell is defined for rotation display. 3, data source A of collectionView is processed. Create an array B, add the last array of A to the first array of B, and add the first array of A to the last array of B. So we have two more data in array B than in our source array A. So in the (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section returns the length of array B, 4, The corresponding human drag operation and scroll are handled in the relevant proxy methods of the ScrollViewCopy the code

The following is the specific implementation of each step in combination with the code.

1> Call this method at regular intervals for scrolling

- (void)startScrollAutomtically {// each time add self.bounds.size.width width [selfsetContentOffset:CGPointMake(self.contentOffset.x + self.bounds.size.width, self.contentOffset.y) animated:YES];
}
Copy the code

If the length of the original data source is greater than one, the timer is started; otherwise, the timer is not started. If the length of the original data source is greater than one, the data source needs to be processed, as described in 3 above. In addition, after refreshing the data source, the default scroll to the first page

- (void)configWithData:(NSArray<id<JWCBannerDataProtocol>> *)datas {
    if (_originalData.count > 1) {
        NSMutableArray *tempArr = [[NSMutableArray alloc] initWithArray:_originalData];
        [tempArr insertObject:[_originalData lastObject] atIndex:0];
        [tempArr addObject:[_originalData firstObject]];
        self.customData = tempArr.copy;
        dispatch_async(dispatch_get_main_queue(), ^{
            [self scrollToPage:1 animated:YES];
        });
        [self startTimer];
        self.isOnlyOne = NO;
    } else{ self.customData = _originalData.copy; [self stopTimer]; self.isOnlyOne = YES; self.currentIndex = 0; }}Copy the code

3> several proxy methods for scrollView

/ / will begin dragging stop timer - (void) scrollViewWillBeginDragging: (UIScrollView *) scrollView {[self stopTimer]; } / / is going to stop dragging start timer - (void) scrollViewWillEndDragging: (UIScrollView *) scrollView withVelocity (CGPoint) velocity targetContentOffset:(inout CGPoint *)targetContentOffset {if(_originaldata.count > 1) {// startTimer [self startTimer] if the data source is greater than 1; }} / / stop dragging the - (void) scrollViewDidEndDecelerating: (UIScrollView *) scrollView {[self checkPageIndx]; } / / stopped animation - (void) scrollViewDidEndScrollingAnimation: (UIScrollView *) scrollView {[self checkPageIndx]; }Copy the code

// This method is manually dragged to complete the desired processing

- (void)checkPageIndx {// When you reach the last image, continue to scroll back to Page 1if(self.contentOffset.x >= (self.customData.count - 1) * self.bounds.size.width) { [self scrollToPage:1 animated:NO]; } // When scrolling to the first image, scroll forward to the second to lastif(self.contentOffset.x < 0) { [self scrollToPage:self.customData.count - 2 animated:NO]; }}Copy the code

This method is called whether the offset of the scrollView is changed manually or automatically, so the current index is computed in this method and the index can be used to display the page number

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat width = self.frame.size.width; NSInteger index = (scrollView. ContentOffset. X + width * 0.5)/width;if (index == 0) {
        index = _originalData.count - 1;
    } else if (index >= _customData.count - 1) {
        index = 0;
    } else {
        index = index - 1;
    }
    self.currentIndex = index;
}
Copy the code

Reprint please indicate the source: https://juejin.cn/post/6844903549193699341, thank you!

The above is just a general idea, the specific implementation code in Git

Operator rendering