– contentSize <bounds.size时的奇怪行为

任何人都可以准确地描述-[UIScrollView zoomToRect:animated:] ? 这种方法似乎确实做了一些复杂的事情,但Apple的文档记录很少。

当内容大小小于滚动视图的宽度和/或高度的大小时,我会得到此方法的不可预测的行为。 在某些情况下,此方法会导致滚动视图在应为0时具有负内容偏移。传递稍微不同的rects,它会将内容偏移量保留为0,就像我期望的那样。

为了演示这种奇怪的行为,我设置了一个示例项目,其中包含大小(200,200)滚动视图,其中包含大小(100,100 内容视图 。 我希望缩放到内容视图的rect((0,0),(200,200))应该将内容留在左上角(即不应该发生任何事情 )。 但是,它实际上会导致内容滚动到滚动视图边界的右下角(内容偏移量(-100,-100))。 为什么会这样?

屏幕录制

这是我的示例项目中的代码:

 @implementation RootViewController - (void)loadView { self.view = [[UIView alloc] init]; self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)]; self.scrollView.delegate = self; self.scrollView.backgroundColor = [UIColor whiteColor]; self.scrollView.minimumZoomScale = .5; self.scrollView.maximumZoomScale = 4; self.contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; self.contentView.backgroundColor = [UIColor redColor]; [self.contentView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap)]]; [self.scrollView addSubview:self.contentView]; self.scrollView.contentSize = self.contentView.frame.size; [self.view addSubview:self.scrollView]; } - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { return self.contentView; } - (void)handleTap { [self.scrollView zoomToRect:CGRectMake(0, 0, 200, 200) animated:YES]; // Try changing to 199, 199 to get completely different behavior } @end 

感谢您的任何见解! 现在我猜UIScrollView只是不是为了显示小于自己大小的内容。 我的用例是我的内容视图比滚动视图宽,但高度更短,我需要能够以编程方式滚动到此内容视图的右端或左端。

除非有人有更好的答案,否则我将得出结论,当结果contentSize小于任一维度中的bounds大小时,调用-zoomToRect:animated:会有未定义的结果。 换句话说,如果您想要安全,内容应该大于滚动视图。

如果有人想知道,这就是我在这种情况下可以做的事情。 我将看看它是否适用于我在现实生活项目中实现的滚动视图子类的unit testing。 然而,这并没有回答原来的问题:“任何人都能准确地描述-[UIScrollView zoomToRect:animated:]吗?” 所以我仍然希望得到更多答案。

嗯,这里(我讨厌像这样的hackery):

 @implementation TBScrollView // Subclass of UIScrollView - (void)setContentOffset:(CGPoint)contentOffset { contentOffset.x = MAX(contentOffset.x, 0); contentOffset.y = MAX(contentOffset.y, 0); [super setContentOffset:contentOffset]; } - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated { contentOffset.x = MAX(contentOffset.x, 0); contentOffset.y = MAX(contentOffset.y, 0); [super setContentOffset:contentOffset animated:animated]; } @end 

编辑:不幸的是,这有一个不幸的副作用,你不能再在左侧反弹滚动更大的图像应该允许(需要负内容偏移)。 我要为我的用例寻找另一种解决方案。

编辑2:我通过仅禁用负内容偏移来解决上述副作用,而-zoomToRect:animated:动画正在进行中。 我声明了一个BOOL属性,在调用-zoomToRect:animated:之前将其设置为YES ,如果animatedNO ,则将其设置为NO 。 否则,我在-scrollViewDidEndScrollingAnimation:期间将属性设置为NO -scrollViewDidEndScrollingAnimation:如果-zoomToRect:animated:没有引起任何比例变化)和-scrollViewDidEndZooming:withView:atScale:如果-zoomToRect:animated:确实引起了更改)规模)。 这是一个hacky解决方案,我担心它可能会破坏未来的iOS版本,但至少我有所有支持unit testing:)