UIScrollView Infinite Scrolling

前端 未结 10 1877
伪装坚强ぢ
伪装坚强ぢ 2020-11-27 13:45

I\'m attempting to setup a scrollview with infinite (horizontal) scrolling.

Scrolling forward is easy - I have implemented scrollViewDidScroll, and when the contentO

10条回答
  •  醉梦人生
    2020-11-27 14:02

    So one issue is that setting the contentOffset while in the scrollViewDidScroll: delegate method will cause the delegate method to fire again while you are inside it. So what I do is remove the delegate > setContentOffset > set the delegate again.

    Here's my code:

    #import "ViewController.h"
    
    @interface ViewController () 
    @property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
    @property (strong, nonatomic) NSMutableArray *labels;
    @property (weak, nonatomic) UILabel *originLabel;
    
    - (void)addScrollViewLabels;
    - (void)adjustOrigins:(float)deltaX;
    
    @end
    
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        // just some starting size
        CGSize size = self.scrollView.frame.size;
        CGSize contentSize = CGSizeMake(size.width * 4, size.height);
        [self.scrollView setContentSize:contentSize];
    
        // just some starting offset
        CGPoint contentOffset = CGPointMake((contentSize.width / 2), 0);
        [self.scrollView setContentOffset:contentOffset];
    
        [self addScrollViewLabels];
    }
    
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
        CGSize contentSize = scrollView.contentSize;
        CGSize size = scrollView.frame.size;
        CGPoint contentOffset = scrollView.contentOffset;
    
        const float kContentOffsetBuffer = 100;
        const float kContentSizeGrowth = (4 * size.width);
    
        BOOL shouldGrowContentSize = (contentOffset.x > (contentSize.width - size.width - kContentOffsetBuffer))
                                    || (contentOffset.x < (kContentOffsetBuffer));
        if (shouldGrowContentSize) {
            // the contentOffset has reached a point where we need to grow the contentSize
            CGSize adjustedContentSize = CGSizeMake(contentSize.width + kContentSizeGrowth, contentSize.height);
            [self.scrollView setContentSize:adjustedContentSize];
    
            if(contentOffset.x < (kContentOffsetBuffer)) {
                // the growth needs to happen on the left side which means that we need to adjust the contentOffset to compensate for the growth.
                // this is not necessary when growth happens to the right since the contentOffset is the same.
                CGPoint adjustedContentOffset = CGPointMake(contentOffset.x + kContentSizeGrowth, contentOffset.y);
                [self.scrollView setDelegate:nil];
                [self.scrollView setContentOffset:adjustedContentOffset];
                [self.scrollView setDelegate:self];
                [self adjustOrigins:kContentSizeGrowth];
            }
    
            [self addScrollViewLabels];
        }
    }
    
    
    - (void)addScrollViewLabels {
        const float kOriginY = 100;
    
        if (!self.labels) {
            self.labels = [NSMutableArray array];
            float originX = [self.scrollView contentOffset].x;
            UILabel *label0 = [[UILabel alloc] initWithFrame:CGRectMake(originX, kOriginY, 100, 30)];
            label0.text = @"0";
            [self.scrollView addSubview:label0];
            [self.labels addObject:label0];
            self.originLabel = label0;
        }
    
        CGSize contentSize = [self.scrollView contentSize];
        const float kIncrementAmount = 75;
        NSInteger indexOfOriginLabel = [self.labels indexOfObject:self.originLabel];
    
        // add labels to the right
        UILabel *lastLabel = [self.labels lastObject];
        float lastOriginX = lastLabel.frame.origin.x;
        for (float x = (lastOriginX + kIncrementAmount); (x < (contentSize.width)) ; x += kIncrementAmount) {
            UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(x, kOriginY, 100, 30)];
            NSInteger indexFromOrigin = ([self.labels count] - indexOfOriginLabel);
            label.text = [@(indexFromOrigin) description];
            [self.scrollView addSubview:label];
            [self.labels addObject:label];
            [label setNeedsDisplay];
        }
    
        // add labels to the left
        UILabel *firstLabel = [self.labels firstObject];
        float firstOriginX = firstLabel.frame.origin.x;
        for (float x = (firstOriginX - kIncrementAmount); (x >= 0) ; x -= kIncrementAmount) {
            UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(x, kOriginY, 100, 30)];
            NSInteger indexFromOrigin = -(indexOfOriginLabel + 1);
            label.text = [@(indexFromOrigin) description];
            [self.scrollView addSubview:label];
            [self.labels insertObject:label atIndex:0];
            indexOfOriginLabel++;
            [label setNeedsDisplay];
        }
    }
    
    - (void)adjustOrigins:(float)deltaX {
        for (UILabel *label in self.labels) {
            CGRect frame = label.frame;
            frame.origin.x += deltaX;
            [label setFrame:frame];
            [label setNeedsDisplay];
        }
    }
    
    
    @end
    

提交回复
热议问题