Ответ
Да, реализовывал. Механизм встроенного зума в UIScrollView требует правильной настройки делегата и вью для масштабирования.
Базовая реализация:
class ZoomableImageView: UIScrollView, UIScrollViewDelegate {
let imageView = UIImageView()
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
private func setup() {
// 1. Добавляем вью для масштабирования
imageView.contentMode = .scaleAspectFit
addSubview(imageView)
// 2. Настраиваем scrollView
minimumZoomScale = 1.0
maximumZoomScale = 4.0
delegate = self
showsHorizontalScrollIndicator = false
showsVerticalScrollIndicator = false
// 3. Добавляем жесты (опционально)
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
doubleTap.numberOfTapsRequired = 2
addGestureRecognizer(doubleTap)
}
// 4. Обязательный метод делегата
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
// 5. Обработка двойного тапа для зума
@objc func handleDoubleTap(_ recognizer: UITapGestureRecognizer) {
if zoomScale > minimumZoomScale {
setZoomScale(minimumZoomScale, animated: true)
} else {
let tapPoint = recognizer.location(in: imageView)
let zoomRect = CGRect(x: tapPoint.x, y: tapPoint.y, width: 1, height: 1)
zoom(to: zoomRect, animated: true)
}
}
}
Ключевые моменты:
viewForZooming(in:): Должен возвращать единственную вью, которую нужно масштабировать.contentSize: Обычно выставляется равным размеру содержимого (например,imageView.frame.size).- Конфликты жестов: Если внутри
UIScrollViewесть другие интерактивные элементы (кнопки, коллекции), может потребоваться обработка черезgestureRecognizer(_:shouldRecognizeSimultaneouslyWith:). contentInsetAdjustmentBehavior: Важно для корректного отображения на устройствах с "чёлкой" (iPhone X и новее).