UIScrollView 更改 contentOffset 时更改框架

Posted

技术标签:

【中文标题】UIScrollView 更改 contentOffset 时更改框架【英文标题】:UIScrollView change contentOffset when change frame 【发布时间】:2014-02-14 18:55:40 【问题描述】:

我在更改滚动视图的框架时遇到了一些问题...有时这种更改会导致滚动,有时不会。

情况是这样的。我有一个自定义 UIScrollView 作为我的根视图控制器的子视图。 在父视图控制器中,我有一个按钮来更改滚动视图的框架。它在屏幕的 2/3 和全屏之间切换。此帧更改不会导致滚动视图的 contentOffset 发生更改。

在滚动视图的内容中,我有一些按钮。这个按钮也改变了滚动视图的框架。 但是,有时,此更改会使滚动视图更改其 contentOffset...

我不明白为什么滚动视图中的按钮会导致这个...

我已经尝试在触摸按钮时调用委托(并在父视图控制器中更改滚动视图的框架)。 并试图改变滚动视图内的框架(当按钮被触摸时)。但问题发生的方式相同。

知道发生了什么或解决这种情况的方法吗?

谢谢!


我试图隔离问题,在这里放一些简单的代码示例。

在我的 xib 中只有一个带有框架 ((20,44),(728,300)) 的滚动视图和一个调用事件“btnOut”的按钮。 该滚动视图启用了分页并禁用了自动调整子视图(其余为默认值)。

我将使用布尔值来判断滚动视图是否大(bigScroll)。

这是我的 viewDidLoad:

- (void)viewDidLoad

    [super viewDidLoad];
    // the initial frame of scrollView is the big frame
    _bigScroll = YES;

    // here I put a big content to create some pages in scrollView
    [_scrollView setContentSize:CGSizeMake(2184, 300)];

    // I put one button in each column
    // When scrollView is with big frame it shows two columns and when it is with small frame it shows only one column.

    UIButton *btn01 = [UIButton buttonWithType:UIButtonTypeSystem];
    [btn01 setFrame:CGRectMake(159, 30, 46, 30)];
    [btn01 setTitle:@"01" forState:UIControlStateNormal];
    [btn01 addTarget:self action:@selector(btnIn:) forControlEvents:UIControlEventTouchDown];
    [_scrollView addSubview:btn01];

    UIButton *btn02 = [UIButton buttonWithType:UIButtonTypeSystem];
    [btn02 setFrame:CGRectMake(523, 30, 46, 30)];
    [btn02 setTitle:@"02" forState:UIControlStateNormal];
    [btn02 addTarget:self action:@selector(btnIn:) forControlEvents:UIControlEventTouchDown];
    [_scrollView addSubview:btn02];

    UIButton *btn03 = [UIButton buttonWithType:UIButtonTypeSystem];
    [btn03 setFrame:CGRectMake(887, 30, 46, 30)];
    [btn03 setTitle:@"03" forState:UIControlStateNormal];
    [btn03 addTarget:self action:@selector(btnIn:) forControlEvents:UIControlEventTouchDown];
    [_scrollView addSubview:btn03];

    UIButton *btn04 = [UIButton buttonWithType:UIButtonTypeSystem];
    [btn04 setFrame:CGRectMake(1251, 30, 46, 30)];
    [btn04 setTitle:@"04" forState:UIControlStateNormal];
    [btn04 addTarget:self action:@selector(btnIn:) forControlEvents:UIControlEventTouchDown];
    [_scrollView addSubview:btn04];

    UIButton *btn05 = [UIButton buttonWithType:UIButtonTypeSystem];
    [btn05 setFrame:CGRectMake(1615, 30, 46, 30)];
    [btn05 setTitle:@"05" forState:UIControlStateNormal];
    [btn05 addTarget:self action:@selector(btnIn:) forControlEvents:UIControlEventTouchDown];
    [_scrollView addSubview:btn05];

    UIButton *btn06 = [UIButton buttonWithType:UIButtonTypeSystem];
    [btn06 setFrame:CGRectMake(1979, 30, 46, 30)];
    [btn06 setTitle:@"06" forState:UIControlStateNormal];
    [btn06 addTarget:self action:@selector(btnIn:) forControlEvents:UIControlEventTouchDown];
    [_scrollView addSubview:btn06];

“btnIn”和“btnOut”两个动作调用相同的函数 (changeFrameScrollView)。

- (void)changeFrameScrollView 
    _bigScroll = !_bigScroll;

    if (_bigScroll) 
        [_scrollView setFrame:CGRectMake(20, 44, 728, 300)];
     else 
        [_scrollView setFrame:CGRectMake(20, 44, 364, 300)];
    

我的预期: 使用滚动视图之外的按钮,框架更改按我的预期工作。

如果更改为小框架,则会从右侧隐藏该列并继续从左侧显示该列。 如果它变成大框架,它会从右侧显示列并且不要移动 contentOffset。

** 独立于我正在查看的页面。

问题: 有时,使用滚动视图内的按钮,框架更改会导致 contentOffset 发生更改。

嗯...我不能解释得这么好,所以我举了一个小例子。

【问题讨论】:

也许一些代码会有所帮助。另外,描述内容偏移量的变化。 【参考方案1】:

我发现这是导致该问题的私有方法 => _adjustContentOffsetIfNecessary

它在某些情况下会改变偏移量,而在其他情况下不会改变。就像我在示例中解释的那样。

如果禁用分页,则不会调用该私有方法,因此为了解决我的问题,我创建了 UIScrollView 的子类并覆盖方法 touchesShouldBegin(仅在按下 scrollView 内的按钮时调用)并禁用分页:

- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view 
    [self setPagingEnabled:NO];
    return YES;

要再次启用分页,我使用委托scrollViewWillBeginDragging

这样做,当我更改框架时 contentOffset 不会改变,并且 scrollView 继续使用分页。

【讨论】:

【参考方案2】:

以下是可能发生的情况:

假设你有一个带有

的滚动视图
contentSize.height   |  200 
frame.size.height    |  100
contentOffset.y      |    0

那么一半的内容将是不可见的。如果你改变frame

frame.size height    |  200

contentOffset 不应更改。

但是,如果您以

开头
contentSize.height   |  200 
frame.size.height    |  100
contentOffset.y      |  100  

并做同样的改变,我想滚动视图会尝试将其内容放入可见框架中,所以你最终会得到 ​​p>

contentOffset.y      |    0

再次,有效地将其从 100 更改为 0。

【讨论】:

在这种情况下,更改是可以接受的,因为它没有更多可显示的内容,因此它调整 contentOffset 以适应可见框架,如您所说。但在我的情况下,调整发生在内容的中间......而且我无法理解。我放了一些代码来显示正在发生的事情。感谢您的关注!

以上是关于UIScrollView 更改 contentOffset 时更改框架的主要内容,如果未能解决你的问题,请参考以下文章

UIScrollView 更改 contentOffset 时更改框架

为啥 uiscrollview 不显示 contentOffset 更改?

UIScrollView 布局更改

更改 UIScrollView 中的比例因子

更改 UIScrollView 中间按钮的大小

使用 UIScrollView 更改图像的 alpha