使用内容插入启用的 UIScrollView 分页工作很奇怪

Posted

技术标签:

【中文标题】使用内容插入启用的 UIScrollView 分页工作很奇怪【英文标题】:UIScrollView paging enabled with content inset is working strange 【发布时间】:2013-09-28 13:23:53 【问题描述】:

我创建了带有内容插入的 UIScrollView。

scrollView.frame = CGRectMake(-80, 180, 480, 190)
self.scrollView.contentInset = UIEdgeInsetsMake(0, 160, 0, 160);
self.scrollView.pagingEnabled = YES;
[self.scrollView setContentSize:CGSizeMake(480, 190)];

// Add three Views
[self.scrollView addSubview:view1];
[self.scrollView addSubview:view2];
[self.scrollView addSubview:view3];

[view1 setFrame:CGRectMake(0, 0, 160, 190)];
[view2 setFrame:CGRectMake(160, 0, 160, 190)];
[view3 setFrame:CGRectMake(320, 0, 160, 190)];

第一次时,scrollView.contentOffset.x 是 -160.0

但奇怪的问题是当我点击滚动视图(黄色区域)时,内容偏移 x 值重置为 0 并显示如下。

我尝试了几次,但点击滚动视图会将内容偏移重置为 0。

如何防止这种情况发生?

【问题讨论】:

scrollView的框架是什么? scrollView.frame = CGRectMake(-80, 180, 480, 190)。我要制作类似的画廊。 【参考方案1】:

UIScrollView 分页通过滚动具有与 scrollView 相同宽度的页面(在您的情况下为 480 宽度的页面)来工作。这意味着您有 1 个单页(由于插入了 160 个内容,您仍然可以左右滚动)。

完成这项工作的一种方法是:

self.scrollView.frame = CGRectMake(80, 180, 160, 190);
self.scrollView.clipsToBounds = NO;
self.scrollView.contentInset = UIEdgeInsetsZero;
self.scrollView.pagingEnabled = YES;
[self.scrollView setContentSize:CGSizeMake(480, 190)];

这将正确地绘制和滚动,但是,屏幕的两侧将无法交互(每侧 80 像素,因为控件从 frame.origin.x=80 开始并在 80+160=240 结束)。

第二种选择是自己处理分页,使用UIScrollViewDelegate提供的方法。

- (void)viewDidLoad

    [super viewDidLoad];
    // pageIndex must be declared as a class member - this is used to prevent skipping pages during scroll
    pageIndex = 0;
    self.scrollView.frame = CGRectMake(0, 180, 320, 190);
    self.scrollView.contentInset = UIEdgeInsetsMake(0, 80, 0, 80);
    self.scrollView.pagingEnabled = NO;
    self.scrollView.clipsToBounds = YES;
    [self.scrollView setContentSize:CGSizeMake(480, 190)];
    self.scrollView.delegate = self;


- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
    int pageWidth = 160;
    int pageX = pageIndex*pageWidth-scrollView.contentInset.left;
    if (targetContentOffset->x<pageX) 
        if (pageIndex>0) 
            pageIndex--;
        
    
    else if(targetContentOffset->x>pageX)
        if (pageIndex<3) 
            pageIndex++;
        
    
    targetContentOffset->x = pageIndex*pageWidth-scrollView.contentInset.left;
    NSLog(@"%d %d", pageIndex, (int)targetContentOffset->x);

【讨论】:

我需要分页和内容插入,因为我想看到内容视图之外的内容。 滚动视图没有单页,因为它有contentInset,它有3页 页面宽度为480(因为那是你的scrollview)的宽度;insets一起320,小于1页。无论如何,使用contentInset是不是要走的路,因为它不能很好地进行分页,并且页面不会包含您期望的视图,除非您将每个视图居中在其 480 宽的页面内。 可以看代码,一页宽度=scrollview width(480)-insets(320)=160,内容宽度=480,所以page=3 它不是那样工作的。在pagingEnabled 的文档中说:If the value of this property is YES, the scroll view stops on multiples of the scroll view’s bounds when the user scrolls。边界不受contentInset的影响。【参考方案2】:

除了 alex 将 clipsToBounds 设置为 NO 的第一种方法之外,我还需要对滚动视图边界之外的滚动做出反应。所以我创建了 ScrollForwarderView 类,它是 UIView 的子类。

ScrollForwarderView.h

#import <UIKit/UIKit.h>

@interface ScrollForwarderView : UIView
@property (nonatomic, weak) UIScrollView *scrollView;
@end

ScrollForwarderView.m

...
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
    if ([self pointInside:point withEvent:event]) 
        return _scrollView;
    
    return nil;

然后将带有自定义类 ScrollForwarderView 的 UIView 放在滚动视图上方,将 scrollView 属性链接到我的滚动视图,它将用户事件很好地转发到滚动视图。

【讨论】:

以上是关于使用内容插入启用的 UIScrollView 分页工作很奇怪的主要内容,如果未能解决你的问题,请参考以下文章

启用分页的 UISCrollview

如何在启用分页的情况下实现 UIScrollView 平铺?

如何在启用分页的 UIScrollView 中延迟加载 100 多个页面?

UIScrollView 和 UIImage 在其中启用了分页

iphone:UIScrollView 分页启用,无缩放和无预览

UITextView 在分页 UIScrollView 内滚动不起作用