検証環境:
Xcode 11.1
Swift 5.1
画像1枚を表示するシンプルな画像ビューワを実装してみる。
画像はピンチで拡大縮小ができるようにする。
実装方法としては UIScrollView 上に UIImageView を配置して実現する。
ただ乗せるだけだと画像の起点が左上になるが UIScrollView の contentInset を設定することで画面の中央に配置できる。
画像のズームは
- スクロールビュー上のズームさせるビューを返すデリゲートメソッド viewForZoomingInScrollView の実装
- スクロールビューの
minimumZoomScale
、maximumZoomScale
を設定
の2つが必要。
コード
Storyboard 側で UIScrollView を画面いっぱいに貼り付けてある。
class ImageViewerViewController: UIViewController, UIScrollViewDelegate { @IBOutlet private weak var scrollView: UIScrollView! private let minZoomScale: CGFloat = 1.0 private let maxZoomScale: CGFloat = 4.0 private var imageView: UIImageView = { let image = UIImage(named: "dog")! let imageView = UIImageView(image: image) // アスペクト比固定でフィットさせる imageView.contentMode = .scaleAspectFit return imageView }() override func viewDidLoad() { super.viewDidLoad() setupScrollView() } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() adjustImageViewSize() updateContentInset() } private func setupScrollView() { scrollView.delegate = self scrollView.backgroundColor = .black scrollView.minimumZoomScale = minZoomScale scrollView.maximumZoomScale = maxZoomScale scrollView.showsVerticalScrollIndicator = false scrollView.showsHorizontalScrollIndicator = false scrollView.addSubview(imageView) } // 画像のアスペクト比を維持したまま ScrollView の表示範囲にぴったり収まるように ImageView のサイズを調整する private func adjustImageViewSize() { guard let size = imageView.image?.size, imageView.frame.isEmpty else { return } let wRate = scrollView.bounds.width / size.width let hRate = scrollView.bounds.height / size.height let rate = min(wRate, hRate, 1) imageView.frame.size = CGSize(width: size.width * rate, height: size.height * rate) // contentSize を画像サイズと同じにする scrollView.contentSize = imageView.frame.size } // ImageView のサイズが ScrollView の表示範囲より小さい場合に画面中央に配置されるように contentInset を設定する private func updateContentInset() { scrollView.contentInset = UIEdgeInsets( top: max((scrollView.frame.height - imageView.frame.height) / 2, 0), left: max((scrollView.frame.width - imageView.frame.width) / 2, 0), bottom: 0, right: 0 ) } // ズーム対象のビューを返す func viewForZooming(in scrollView: UIScrollView) -> UIView? { return imageView } // ズームのタイミングで contentInset を更新する func scrollViewDidZoom(_ scrollView: UIScrollView) { updateContentInset() } }
参考:
UIScrollViewの中央にUIImageViewを配置しつつズーム可能にする - Qiita
https://qiita.com/wmoai/items/52b1901e62d28dae9f91