这是我的解决方案,可与任何选项卡栏或导航栏组合或两者都通用,无论是否半透明。
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
// The scroll view has zoomed, so you need to re-center the contents
CGSize scrollViewSize = [self scrollViewVisibleSize];
// First assume that image center coincides with the contents box center.
// This is correct when the image is bigger than scrollView due to zoom
CGPoint imageCenter = CGPointMake(self.scrollView.contentSize.width/2.0,
self.scrollView.contentSize.height/2.0);
CGPoint scrollViewCenter = [self scrollViewCenter];
//if image is smaller than the scrollView visible size - fix the image center accordingly
if (self.scrollView.contentSize.width < scrollViewSize.width) {
imageCenter.x = scrollViewCenter.x;
}
if (self.scrollView.contentSize.height < scrollViewSize.height) {
imageCenter.y = scrollViewCenter.y;
}
self.imageView.center = imageCenter;
}
//return the scroll view center
- (CGPoint)scrollViewCenter {
CGSize scrollViewSize = [self scrollViewVisibleSize];
return CGPointMake(scrollViewSize.width/2.0, scrollViewSize.height/2.0);
}
// Return scrollview size without the area overlapping with tab and nav bar.
- (CGSize) scrollViewVisibleSize {
UIEdgeInsets contentInset = self.scrollView.contentInset;
CGSize scrollViewSize = CGRectStandardize(self.scrollView.bounds).size;
CGFloat width = scrollViewSize.width - contentInset.left - contentInset.right;
CGFloat height = scrollViewSize.height - contentInset.top - contentInset.bottom;
return CGSizeMake(width, height);
}
斯威夫特 5:
public func scrollViewDidZoom(_ scrollView: UIScrollView) {
centerScrollViewContents()
}
private var scrollViewVisibleSize: CGSize {
let contentInset = scrollView.contentInset
let scrollViewSize = scrollView.bounds.standardized.size
let width = scrollViewSize.width - contentInset.left - contentInset.right
let height = scrollViewSize.height - contentInset.top - contentInset.bottom
return CGSize(width:width, height:height)
}
private var scrollViewCenter: CGPoint {
let scrollViewSize = self.scrollViewVisibleSize()
return CGPoint(x: scrollViewSize.width / 2.0,
y: scrollViewSize.height / 2.0)
}
private func centerScrollViewContents() {
guard let image = imageView.image else {
return
}
let imgViewSize = imageView.frame.size
let imageSize = image.size
var realImgSize: CGSize
if imageSize.width / imageSize.height > imgViewSize.width / imgViewSize.height {
realImgSize = CGSize(width: imgViewSize.width,height: imgViewSize.width / imageSize.width * imageSize.height)
} else {
realImgSize = CGSize(width: imgViewSize.height / imageSize.height * imageSize.width, height: imgViewSize.height)
}
var frame = CGRect.zero
frame.size = realImgSize
imageView.frame = frame
let screenSize = scrollView.frame.size
let offx = screenSize.width > realImgSize.width ? (screenSize.width - realImgSize.width) / 2 : 0
let offy = screenSize.height > realImgSize.height ? (screenSize.height - realImgSize.height) / 2 : 0
scrollView.contentInset = UIEdgeInsets(top: offy,
left: offx,
bottom: offy,
right: offx)
// The scroll view has zoomed, so you need to re-center the contents
let scrollViewSize = scrollViewVisibleSize
// First assume that image center coincides with the contents box center.
// This is correct when the image is bigger than scrollView due to zoom
var imageCenter = CGPoint(x: scrollView.contentSize.width / 2.0,
y: scrollView.contentSize.height / 2.0)
let center = scrollViewCenter
//if image is smaller than the scrollView visible size - fix the image center accordingly
if scrollView.contentSize.width < scrollViewSize.width {
imageCenter.x = center.x
}
if scrollView.contentSize.height < scrollViewSize.height {
imageCenter.y = center.y
}
imageView.center = imageCenter
}
为什么它比我迄今为止在 SO 上能找到的任何东西都好:
它不会读取或修改图像视图的 UIView 框架属性,因为缩放的图像视图对其应用了变换。请参阅此处Apple 关于如何在应用非身份转换时移动或调整视图大小的说明。
从引入条形半透明的 iOS 7 开始,系统将自动调整滚动视图大小、滚动内容插入和滚动指示器偏移。因此,您也不应该在代码中修改这些内容。
仅供参考:在 Xcode 界面构建器中有用于切换此行为(默认设置)的复选框。您可以在视图控制器属性中找到它:
完整视图控制器的源代码在此处发布。
您还可以下载整个 Xcode 项目以查看滚动视图约束设置,并通过将初始控制器指针移动到以下任何路径来在情节提要中使用 3 个不同的预设:
- 使用半透明选项卡和导航栏查看。
- 使用不透明选项卡和导航栏查看。
- 查看完全没有条形图。
每个选项都适用于相同的 VC 实现。