可以将行为更改为围绕中心进行缩放,但该技术很棘手。
假设您有一个大小为 (300,300) 的滚动视图,其中包含一个可缩放的子视图 self.imageView,最初位于 (0,0,300,300)。现在你想缩小。正在发生的事情是,当您缩小时,contentOffset 始终保持 (0,0)。这会导致您使用左上角的锚点进行缩放。
但是,在这里更改任何视图上的锚点都无济于事;这是因为滚动视图的缩放行为不仅仅是应用于某些子视图的缩放转换。滚动视图中内容的外观由contentInset 和contentOffset 控制,它们是滚动视图维护的独立变量。您需要在缩放期间修改内容偏移和内容插入的行为。
一种解决方案是在滚动视图滚动时动态调整contentInset。目的是使图像始终居中于滚动视图的可见区域。
在初始化滚动视图时,像这样准备它的框架:
- (void) viewDidLoad {
//// .......
self.scrollView.zoomScale = 1;
self.scrollView.minimumZoomScale = fminf(1, fminf(self.scrollView.frame.size.width/(self.imageView.image.size.width+1), self.scrollView.frame.size.height/(self.imageView.image.size.height+1)));
CGFloat leftMargin = (self.scrollView.frame.size.width - self.imageView.image.size.width)*0.5;
CGFloat topMargin = (self.scrollView.frame.size.height - self.imageView.image.size.height)*0.5;
self.imageView.frame = CGRectMake(0, 0, self.imageView.image.size.width, self.imageView.image.size.height);
[self assignInsetsOnScroller]; // this has to be done before settings contentOffset!
self.scrollView.contentOffset = CGPointMake(fmaxf(0,-leftMargin), fmaxf(0,-topMargin));
self.scrollView.contentSize = CGSizeMake(fmaxf(self.imageView.image.size.width, self.scrollView.frame.size.width+1), fmaxf(self.imageView.image.size.height, self.scrollView.frame.size.height+1));
}
为滚动视图设置一个委托,覆盖scrollViewDidScroll:,然后执行以下操作:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self assignInsetsOnScroller];
}
- (void) assignInsetsOnScroller {
CGFloat leftMargin = (scrollView.frame.size.width - self.imageView.frame.size.width)*0.5;
CGFloat topMargin = (scrollView.frame.size.height - self.imageView.frame.size.height)*0.5;
scrollView.contentInset = UIEdgeInsetsMake(fmaxf(0, topMargin), fmaxf(0, leftMargin), 0, 0);
}
每个捏合手势都会产生滚动动作。结果是动态调整了插图,因此imageView 总是出现在滚动视图的中心。
Swift 5:要简单得多。无需进行任何设置 — 只需在 scrollViewDidScroll 中设置 contentOffset。
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let leftMargin = (scrollView.bounds.width - imageView.frame.width) * 0.5
let topMargin = (scrollView.bounds.height - imageView.frame.height) * 0.5
scrollView.contentInset = UIEdgeInsets(top: topMargin, left: leftMargin, bottom: 0, right: 0)
}