Ios -[UIScrollView zoomToRect:animated:]contentSize时的怪异行为<;大小
有人能准确描述Ios -[UIScrollView zoomToRect:animated:]contentSize时的怪异行为<;大小,ios,objective-c,uiscrollview,Ios,Objective C,Uiscrollview,有人能准确描述-[UIScrollView zoomToRect:animated:][/code>的行为吗?这种方法看起来确实做了一些复杂的事情,但苹果公司关于它的文档非常稀少 当内容大小在宽度和/或高度上小于滚动视图的大小时,这种方法会出现不可预测的行为。在某些情况下,此方法会导致滚动视图在其应为0时具有负内容偏移。通过稍微不同的矩形,它将内容偏移量保留为0,这与我预期的一样 为了演示这种奇怪的行为,我设置了一个示例项目,其中包含一个大小为(200200)的滚动视图,其中包含一个大小为(10
-[UIScrollView zoomToRect:animated:][/code>的行为吗?这种方法看起来确实做了一些复杂的事情,但苹果公司关于它的文档非常稀少
当内容大小在宽度和/或高度上小于滚动视图的大小时,这种方法会出现不可预测的行为。在某些情况下,此方法会导致滚动视图在其应为0时具有负内容偏移。通过稍微不同的矩形,它将内容偏移量保留为0,这与我预期的一样
为了演示这种奇怪的行为,我设置了一个示例项目,其中包含一个大小为(200200)的滚动视图,其中包含一个大小为(100100)的内容视图。我希望缩放到内容视图的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
的设计并不是为了显示小于自身大小的内容。我的使用案例是,我的内容视图可能比滚动视图宽,但高度较短,并且我需要能够以编程方式滚动到此内容视图的右端或左端。如果有人想知道,在这种情况下我可能会这样做。我将看看它是否与我在现实项目中实现的scroll view子类的单元测试配合得很好。然而,这并没有回答最初的问题“有人能准确地描述-[UIScrollView zoomToRect:animated:
”所以我仍然希望得到更多的答案
好吧,下面是(我讨厌这样的黑客):
编辑:不幸的是,这有一个不幸的副作用,那就是你不能再在应该允许的较大图像的左侧反弹滚动(需要负内容偏移)。我将为我的用例寻找另一个解决方案
edit2:在进行-zoomToRect:animated:
动画时,我仅通过禁用负内容偏移来避免上述副作用。我声明了一个BOOL
属性,在调用-zoomToRect:animated:
之前将其设置为YES
,如果animated
是NO
,则之后将其设置回NO
。否则,我会在-scrollViewDiEndScrollingAnimation:
期间将属性设置为NO
(如果-zoomToRect:animated:
没有引起任何比例变化,则调用该属性)和-ScrollViewDiEndZooming:withView:atScale:
(如果-zoomToRect:animated:
确实引起了比例变化,则调用该属性)。这是一种黑客解决方案,我担心它可能会在未来的iOS版本中崩溃,但至少我有单元测试支持:)除非有人有更好的答案,我将得出结论,当生成的contentSize
小于任一维度的界限
大小时,调用-zoomToRect:animated:
具有未定义的结果。换句话说,如果您希望安全,内容应该大于滚动视图。内容大小小于边界有什么意义?将未使用的维度设置为与边界匹配,然后继续。哦,iOS将允许您通过滚动到用户无法滚动到的位置来挂起自己。解决方案:不要这样做。@jaggedcow是的,我正在设置contentSize
。即使在这种退化的情况下,我也希望将内容放在左上角。对于您的用例,为什么要使用zoomToRect:而不是scrollToRect:或者只是设置contentOffset?这可能会帮助您查看我的示例:演示如何在保持可缩放视图居中的同时允许缩放。您不需要两种方法;第一个调用第二个。根据我的测试,第一个不调用第二个是的,你是对的,我把它倒过来了:第二个调用第一个。
@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