UIScrollView无限滚动

Ben*_*son 16 iphone uiscrollview

我正在尝试设置无限(水平)滚动的滚动视图.

向前滚动很容易 - 我已经实现了scrollViewDidScroll,当contentOffset接近结尾时,我将使scrollview内容更大,并将更多数据添加到空间中(我将不得不处理稍后会产生的严重影响!)

我的问题是向后滚动 - 计划是看到我何时接近滚动视图的开头,然后当我确实使内容更大时,移动现有内容,将新数据添加到开头然后 - 重要的是调整contentOffset使视图端口下的数据保持不变.

如果我慢慢滚动(或启用分页),这可以很好地工作但如果我快速(甚至不是非常快!)它会发疯!下面是代码:

- (void) scrollViewDidScroll:(UIScrollView *)scrollView {

    float pageNumber = scrollView.contentOffset.x / 320;
    float pageCount = scrollView.contentSize.width / 320;

    if (pageNumber > pageCount-4) {
        //Add 10 new pages to end
        mainScrollView.contentSize = CGSizeMake(mainScrollView.contentSize.width + 3200, mainScrollView.contentSize.height);
        //add new data here at (320*pageCount, 0);
    }

    //*** the problem is here - I use updatingScrollingContent to make sure its only called once (for accurate testing!)
    if (pageNumber < 4 && !updatingScrollingContent) {

        updatingScrollingContent = YES;

        mainScrollView.contentSize = CGSizeMake(mainScrollView.contentSize.width + 3200, mainScrollView.contentSize.height);
        mainScrollView.contentOffset = CGPointMake(mainScrollView.contentOffset.x + 3200, 0);
        for (UIView *view in [mainContainerView subviews]) {
            view.frame = CGRectMake(view.frame.origin.x+3200, view.frame.origin.y, view.frame.size.width, view.frame.size.height);
        }
        //add new data here at (0, 0);      
    }

    //** MY CHECK!
    NSLog(@"%f", mainScrollView.contentOffset.x);
}
Run Code Online (Sandbox Code Playgroud)

当滚动发生时,日志显示为:1286.500000 1285.500000 1284.500000 1283.500000 1282.500000 1281.500000 1280.500000

然后,当pageNumber <4(我们接近开头)时:4479.500000 4479.500000

大! - 但数字应继续在4,000s下降,但下一个日志条目为:1278.000000 1277.000000 1276.500000 1275.500000等....

从它停止的地方继续!

仅为记录,如果慢慢滚动,日志显示:1294.500000 1290.000000 1284.500000 1280.500000 4476.000000 4476.000000 4473.000000 4470.000000 4467.500000 4464.000000 4460.500000 4457.500000等....

有任何想法吗????

谢谢

本.

rwy*_*and 17

我找到了Apple的一个非常好的示例应用程序,用于在OP中使用类似的想法实现Infinite Scrolling.非常简单,最重要的是没有撕裂.

http://developer.apple.com/library/ios/#samplecode/StreetScroller/Introduction/Intro.html

他们每次layoutSubviews在UIScrollView上调用时都实现了"内容重定制" .

我做的唯一调整是回收"平铺效果",而不是扔掉旧瓷砖并分配新瓷砖.


mvd*_*vds 7

可能是因为无论在那里设置这些数字,你都不会将contentOffset置于其手中.所以它只是继续设置它认为应该是下一个瞬间的contentOffset - 而不验证contentOffset是否在此期间发生了变化.

我会继承UIScrollView并将魔法放在setContentOffset方法中.根据我的经验,所有内容偏移更改都会通过该方法,甚至是内部滚动引起的内容偏移更改.只是[super setContentOffset:..]在某些时候将消息传递给真正的UIScrollView.

也许如果你把你的换挡动作放在那里它会更好.您至少可以检测到contentOffset的3000关设置,并在传递消息之前修复它.如果您还要覆盖该contentOffset方法,您可以尝试查看是否可以制作虚拟无限内容大小,并将其减少到"引擎盖下"的实际比例.


Yun*_*hel 6

当我遇到这个问题时,我有3个图像,需要能够向任一方向无限滚动.最佳解决方案可能是在用户移动到最右/最左边的图像时加载3个图像并修改内容面板,但我找到了一个更简单的解决方案.(对代码进行了一些编辑,可能包含错别字)

我设置了一个包含5个图像的滚动视图,而不是3个图像,如:

3 | 1 | 2 | 3 | 1
Run Code Online (Sandbox Code Playgroud)

并相应地计算内容视图,而内容大小是固定的.这是代码:

for ( NSUInteger i = 1; i <= NO_OF_IMAGES_IN_SCROLLVIEW + 2 ; i ++) {

    UIImage *image;
    if ( i  % 3 == 1){

        image = [UIImage imageNamed:[NSString stringWithFormat:@"img1.png"]];
    }

    else if (i % 3 == 2 ) {

        image = [UIImage imageNamed:[NSString stringWithFormat:@"img2.png"]];

    }

    else {

        image = [UIImage imageNamed:[NSString stringWithFormat:@"img3.png"]];
    }

    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake((i-1)*_scrollView.frame.size.width, 0, _scrollView.frame.size.width, _scrollView.frame.size.height)];
    imageView.contentMode=UIViewContentModeScaleToFill;
    [imageView setImage:image];
    imageView.tag=i+1;
    [self.scrollView addSubview:imageView];
}

[self.scrollView setContentOffset:CGPointMake(self.scrollView.frame.size.width, 0)];
[scrMain setContentSize:CGSizeMake(self.scrollView.frame.size.width * ( NO_OF_IMAGES_IN_SCROLLVIEW + 2 ), self.scrollView.frame.size.height)];
Run Code Online (Sandbox Code Playgroud)

现在添加了图像,唯一的事情是创建无限滚动的幻觉.为此,我将用户"传送"到三个主要图像,每当他试图滚动到外部两个图像之一时.非动画非常重要,这样用户就无法感受到:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

    if (scrollView.contentOffset.x < scrollView.frame.size.width ){

        [scrollView scrollRectToVisible:CGRectMake(scrollView.contentOffset.x + 3 * scrollView.frame.size.width, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:NO];
    }
}

    else if ( scrollView.contentOffset.x > 4 * scrollView.frame.size.width  ){

        [scrollView scrollRectToVisible:CGRectMake(scrollView.contentOffset.x - 3 * scrollView.frame.size.width, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:NO];
    }
}
Run Code Online (Sandbox Code Playgroud)


Ben*_*son 5

(希望我正确地发布这个 - 我是新来的!?)

mvds是现货 - 谢谢 - 子类化UIScrollView完美运行 - 我还没有实现新数据的移位和加载,但我有一个UIScrollView在无限循环中滚动!

下面是代码:

#import "BRScrollView.h"

@implementation BRScrollView

- (id)awakeFromNib:(NSCoder *)decoder {
    offsetAdjustment = 0;
    [super initWithCoder:decoder];
    return self;
}

- (void)setContentOffset:(CGPoint)contentOffset {

    float realOffset = contentOffset.x + offsetAdjustment;

    //This happens when contentOffset has updated correctly - there is no need for the adjustment any more
    if (realOffset < expectedContentOffset-2000 || realOffset > expectedContentOffset+2000) {
        offsetAdjustment = 0;
        realOffset = contentOffset.x;
    }

    float pageNumber = realOffset / 320;
    float pageCount = self.contentSize.width / 320;

    if (pageNumber > pageCount-4) {
        offsetAdjustment -= 3200;
        realOffset -= 3200;
    }

    if (pageNumber < 4) {
        offsetAdjustment += 3200;
        realOffset += 3200; 
    }

    //Save expected offset for next call, and pass the real offset on
    expectedContentOffset = realOffset;     
    [super setContentOffset:CGPointMake(realOffset, 0)];


}

- (void)dealloc {
    [super dealloc];
}


@end
Run Code Online (Sandbox Code Playgroud)

笔记:

如果你真的想要一个无限循环,你需要调整数字 - 当你靠近边缘并将你移到中间位置时,这个代码会发出通知

我的contentSize是6720(21页)

我只对水平滚动感兴趣,所以只保存x值并将y硬编码为0!


Raj*_*war 5

我已经制作了一个示例项目来解决您的问题.

你可以从下载代码

https://code.google.com/p/iphone-infinite-horizo​​ntal-scroller/

这无休止地向两个方向滚动并在旅途中加载图像.