无限 UIScrollView 在 iOS 4.3 上不起作用

Posted

技术标签:

【中文标题】无限 UIScrollView 在 iOS 4.3 上不起作用【英文标题】:Infinite UIScrollView not working on iOS 4.3 【发布时间】:2011-12-07 12:37:51 【问题描述】:

我尝试构建一个无限滚动的 UIScrollView。到目前为止,我采用了苹果样本“StreetScroller”。所以我所做的就是在 contentOffset 到达滚动视图的末尾时重新设置它。

覆盖 UIScrollView 的-layoutSubviews

- (void)layoutSubviews

    CGFloat contentWidth = [self contentSize].width;
    CGPoint contentOffset = [self contentOffset];

    CGFloat centerOffsetX = (contentWidth - [self bounds].size.width) / 2.0;
    CGFloat distanceFromCenter = contentOffset.x - centerOffsetX;
    if (ABS(distanceFromCenter) > (contentWidth / 4.0)) 
        contentOffset = CGPointMake(centerOffsetX, contentOffset.y);
        [super setContentOffset:contentOffset];
    

现在在 ios 5 上,这就像一个魅力。但在 iOS 4.3 上它不起作用。一旦我调用[super setContentOffset:contentOffset],它就会停止滚动,因为下次调用-layoutSubviews 时,[self contentOffset] 不会返回设置的contentOffset

我知道有很多关于无限 UIScrollViews 的问题,但其中一个已经解决了这个问题!

【问题讨论】:

这似乎是一个错误:***.com/questions/2168598/… 你也可以试试这个实现:never-ending paging UIScrollView 感谢链接,但这是一个分页解决方案。这对我来说不是一个选择,也从来不是问题。 【参考方案1】:

试试这个。此代码在 iOS 4.3 上对我正常工作

RootViewController.h

@class ViewControllerForDuplicateEndCaps;

@interface RootViewController : UIViewController 

ViewControllerForDuplicateEndCaps *viewControllerForDuplicateEndCaps;


@property (nonatomic, retain) ViewControllerForDuplicateEndCaps *viewControllerForDuplicateEndCaps;

- (IBAction)loadScrollViewWithDuplicateEndCaps:(id)sender; 

@end

RootViewController.m

#import "RootViewController.h"
#import "ViewControllerForDuplicateEndCaps.h"
#import "InfiniteScrollViewAppDelegate.h"

@implementation RootViewController

@synthesize viewControllerForDuplicateEndCaps;


- (IBAction)loadScrollViewWithDuplicateEndCaps:(id)sender 
InfiniteScrollViewAppDelegate *delegate = (InfiniteScrollViewAppDelegate*)[[UIApplication sharedApplication] delegate];

if(self.viewControllerForDuplicateEndCaps == nil) 
    ViewControllerForDuplicateEndCaps *temp = [[ViewControllerForDuplicateEndCaps alloc] initWithNibName:@"ViewControllerForDuplicateEndCaps" bundle:nil];
    self.viewControllerForDuplicateEndCaps = temp;
    [temp release];


UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];

[delegate.navigationController pushViewController:self.viewControllerForDuplicateEndCaps animated:YES];


- (void)dealloc 

[scrollView release];
[super dealloc];
 
@end

ViewControllerForDuplicateEndCaps.h

#import <UIKit/UIKit.h>

@interface ViewControllerForDuplicateEndCaps : UIViewController <UIScrollViewDelegate> 

IBOutlet UIScrollView *scrollView;


@property (nonatomic, retain) UIScrollView *scrollView;

- (void)addImageWithName:(NSString*)imageString atPosition:(int)position;


@end

ViewControllerForDuplicateEndCaps.m

#import "ViewControllerForDuplicateEndCaps.h"

@implementation ViewControllerForDuplicateEndCaps

@synthesize scrollView;


 - (void)viewDidLoad 

 [super viewDidLoad];

// add the last image (image4) into the first position
[self addImageWithName:@"image4.jpg" atPosition:0];

// add all of the images to the scroll view
for (int i = 1; i < 5; i++) 
    [self addImageWithName:[NSString stringWithFormat:@"image%i.jpg",i] atPosition:i];


// add the first image (image1) into the last position
[self addImageWithName:@"image1.jpg" atPosition:5];

scrollView.contentSize = CGSizeMake(1920, 416);    
[scrollView scrollRectToVisible:CGRectMake(320,0,320,416) animated:NO]; 


- (void)addImageWithName:(NSString*)imageString atPosition:(int)position 
// add image to scroll view
UIImage *image = [UIImage imageNamed:imageString];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(position*320, 0, 320, 416);
[scrollView addSubview:imageView];
[imageView release];


- (void)scrollViewDidEndDecelerating:(UIScrollView *)sender     
NSLog(@"%f",scrollView.contentOffset.x);
// The key is repositioning without animation      
if (scrollView.contentOffset.x == 0)          
    // user is scrolling to the left from image 1 to image 4         
    // reposition offset to show image 4 that is on the right in the scroll view         
    [scrollView scrollRectToVisible:CGRectMake(1280,0,320,416) animated:NO];     
    
else if (scrollView.contentOffset.x == 1600)          
    // user is scrolling to the right from image 4 to image 1        
    // reposition offset to show image 1 that is on the left in the scroll view         
    [scrollView scrollRectToVisible:CGRectMake(320,0,320,416) animated:NO];         
 


- (void)dealloc 

[scrollView release];
[super dealloc];

@end

【讨论】:

不抱歉,但这不能按预期工作。我同意这是无休止的滚动,但它不是无缝的。它在到达边界时停止,只有在停止后才重置。我用您的代码建立了一个小型 Xcode 项目。 dl.dropbox.com/u/15892171/InfiniteScrollView.zip

以上是关于无限 UIScrollView 在 iOS 4.3 上不起作用的主要内容,如果未能解决你的问题,请参考以下文章

为啥 UIScrollView 的滚动会在 iOS 4.3 中触发 layoutSubViews 方法,而在 5.0 及以上版本中却没有?

iOS开发系列--无限循环的图片浏览器

UIScrollView 无限滚动 setContentOffset

iOS之深度剖析UIScrollView的实现原理与阻尼动画

在 Swift 中使用 UIScrollView 进行无限循环滚动

在无限 UIScrollView 中跨页面拖动视图