UIScrollView在iPhone / iPad上旋转时禁用滚动

时间:2010-11-08 12:52:48

标签: iphone cocoa-touch uikit uiscrollview

我正在使用UIScrollView及其中的图像作为每页分页一个图像。旋转iPhone

时遇到问题

当我旋转iPhone时,滚动ViewDidScroll(滚动视图委托方法)正在调用。 因此,我的分页受到干扰,页码也会发生变化。

解决方案是什么?

6 个答案:

答案 0 :(得分:23)

Raphaël's answer是对问题的精彩描述,也是一个简洁的解决方案。我有完全相同的问题,并最终修复了一个scrollingLocked标志,我在旋转开始前设置为YES(已锁定),并在结束时设置为NO(已解锁)。也许比暂时改变contentSize稍微不那么苛刻:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
                                duration:(NSTimeInterval)duration
{
    self.photoViewer.scrollingLocked = YES;
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromOrientation
{
    self.photoViewer.scrollingLocked = NO;
}

- (void)scrollViewDidScroll:(UIScrollView*)scrollView
{
    if (self.scrollingLocked)
    {
        return;
    }
    /* do normal scrollViewDidScroll: stuff */
}

答案 1 :(得分:14)

在旋转分页UIScrollView时,我发现了一种奇怪的无证件行为。

当滚动视图位于最后一页并且用户更改方向时,操作系统会向后滚动UIScrollView几个像素以补偿高度和宽度之间的差异。

基本上我收到了以下任何页面的电话。

willRotateToInterfaceOrientation:duration
willAnimateRotationToInterfaceOrientation:duration:
didRotateFromInterfaceOrientation:

最后一页:

willRotateToInterfaceOrientation:duration
scrollViewDidScroll:
willAnimateRotationToInterfaceOrientation:duration:
didRotateFromInterfaceOrientation:

这也搞砸了我的网页。问题是在willRotate中,操作系统尚未更新边界,并且在willAnimate中你有新边界并可以计算新的大小,但为时已晚......

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {

    CGSize tempSize = [self.pagingScrollView contentSize];
    NSUInteger padding = abs(pagingScrollView.frame.size.width - pagingScrollView.frame.size.height);
    tempSize.width += padding;
    [self.pagingScrollView setContentSize:tempSize];
    [...]
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration{
    CGSize newSize = ... // Compute new content size based on new orientation
    [self.pagingScrollView setContentSize:newSize];
}

这只是一种解决方法,但我在这个问题上花了无数个小时,却找不到一个优雅的解决方案。

答案 2 :(得分:0)

我的任务是允许滚动景观。设计是为了肖像。我想出了一个想法,将ScrollView添加到组件,或者在Interface Builder中的“嵌入滚动视图”中。我原以为它会起作用,但没有。我正在使用Xcode 4.4,iOS 5.1,(办公室项目也需要支持4.2),但问题是一样的。

在Stack Overflow问题 iPhone SDK: UIScrollView does not scroll 中,有一行可以解决问题。

其他尝试在Stack Overflow问题 iOS - UIScrollView is not working (it doesn't scroll at all - the image stays fixed) 中,这有助于我和其他人一起使用,所以这是我的移植到可滚动的横向代码:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromOrientation
{ 
    if( UIInterfaceOrientationIsPortrait( [[UIApplication sharedApplication] statusBarOrientation] ) ){
        scrollView.contentSize = portaitScrollSize;
    }
    else{//statusbar is Landscape
        scrollView.contentSize = landscapeScrollSize;
    }    
}

scrollView绑定到Interface Builder中的iVar视图。 portaitScrollSizelandscapeScrollSize是私有变量。它们被初始化并且不会改变。 在my.h文件中:

IBOutlet UIScrollView *scrollView;

my.m档案中:

CGSize portaitScrollSize, landscapeScrollSize;

...

portaitScrollSize = CGSizeMake(320,440);
landscapeScrollSize = CGSizeMake(480,480);

我希望它可以帮助某人为肖像设计添加旋转+滚动功能。

不要忘记在顶级组件

上允许使用portait + landscape
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return TRUE;
}

答案 3 :(得分:0)

除了RaphaëlMor的回答。如果从纵向切换到横向,则内容大小和页面结构将会生效。因此,为了维护当前页面结构,只需将额外的内容大小添加到width:

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
    [self.scrollView setContentSize:CGSizeMake(self.scrollView.contentSize.width + 400, self.scrollView.contentSize.height)];
}

确保在方向改变后再次设置内容大小和偏移量:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    [self.scrollView setContentSize:CGSizeMake(self.scrollView.bounds.size.width *3, self.scrollView.bounds.size.height)];
    [self.scrollView setContentOffset:CGPointMake(self.scrollView.bounds.size.width * self.pageControl.currentPage, 0) animated:NO];

}

答案 4 :(得分:0)

Swift 4解决方案:

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        lui.l("apply previousTraitCollection: \(previousTraitCollection)")
        canScroll = true
    }

答案 5 :(得分:0)

您可以为Swift尝试这种方法:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    coordinator.animate(alongsideTransition: { _ in
      // Execute before rotation
    }) { _ in
      //Execute after rotation
    }
}