これは、タブバーまたはナビゲーションバーの組み合わせ、または両方なしで、半透明かどうかにかかわらず、普遍的に機能する私のソリューションです。
- (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 インターフェイス ビルダーには、この動作を切り替えるためのチェック ボックス (既定で設定されています) があります。ビューコントローラーの属性で見つけることができます:
View Controller の完全なソース コードは、こちらで公開されています。
また、 Xcode プロジェクト全体をダウンロードして、スクロール ビューの制約の設定を確認し、最初のコントローラー ポインターを次のいずれかのパスに移動して、ストーリーボードの 3 つの異なるプリセットを試してみることもできます。
- 半透明のタブ バーとナビゲーション バーの両方を表示します。
- 不透明なタブとナビゲーション バーの両方で表示します。
- バーがまったくないビュー。
すべてのオプションは、同じ VC 実装で正しく機能します。