I have a view with an image. When the image is clicked there is a modal popup of that image that is "full screen" and is zoomable.
The first time the image is clicked the popup looks great, with the image the proper size. But if the popup is closed and reopened, the sizing is off for some reason. I'm not sure what the problem is.
Code:
import UIKit
class ExampleViewController: UIViewController, UIScrollViewDelegate {
//popup itself
@IBOutlet var imageView: UIView!
//scroll view that enables the zoom feature
@IBOutlet weak var scrollView: UIScrollView!
//the image in the popup
@IBOutlet weak var zoomImageView: UIImageView!
//dark background (that is clickable) when the popup is shown
@IBOutlet weak var backgroundButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(true, animated: false)
imageView.layer.cornerRadius = 10
imageView.layer.masksToBounds = true
self.scrollView.minimumZoomScale = 1.0
self.scrollView.maximumZoomScale = 6.0
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.zoomImageView
}
//keeps the image the proper size and centered if the phone rotates while the popup is open
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
if UIDevice.current.orientation.isLandscape{
imageView.center = self.view.center
imageView.frame = view.frame
scrollView.zoomScale = 1.0
} else if UIDevice.current.orientation.isPortrait{
imageView.center = self.view.center
imageView.frame = view.frame
scrollView.zoomScale = 1.0
}
}
//activates when the image is clicked in the superview
@IBAction func showImageView(_ sender: Any) {
animateIn()
}
//activates when the close button is clicked in the popup (or when the backgroundButton is clicked)
@IBAction func closeImageView(_ sender: Any) {
animateOut()
}
func animateIn() {
self.scrollView.zoomScale = 1.0
self.view.addSubview(imageView)
imageView.center = self.view.center
imageView.frame = self.view.frame
imageView.transform = CGAffineTransform.init(scaleX: 1.3, y: 1.3)
imageView.alpha = 0
self.backgroundButton.alpha = 0.7
UIView.animate(withDuration: 0.4) {
self.imageView.alpha = 1
self.imageView.transform = CGAffineTransform.identity
}
}
func animateOut() {
UIView.animate(withDuration: 0.3, animations: {
self.imageView.transform = CGAffineTransform.init(scaleX: 1.3, y: 1.3)
self.imageView.alpha = 0
self.backgroundButton.alpha = 0
}) { (success:Bool) in
self.imageView.removeFromSuperview()
}
}
}
Any help would be greatly appreciated.
The first part of the answer..
You have source code lines like this:
imageView.frame = self.view.frame
which are potentially a problem, for two separate reasons:
1. You are at times applying a transform to imageView. Whenever a view has a non-identity transform, its frame property is meaningless, and attempts to resize the view by setting the frame may do the wrong thing. That might explain why it works the first time (imageView has an identity transform when you set the frame at the first animate-in), but fails later (imageView has a non-identity transform left over from the last animate-out), but I'm not sure I'm reading the sequence of events in your code correctly.
Instead, for a transformed view, you should set the center and bounds properties. (The bounds represents the untransformed view size.)
2. You're mixing coordinate systems. The frame of imageView is in the bounds coordinate system of its superview (i.e. self.view), and the frame of self.view is in the bounds coordinate system of its superview (or the window, if it has no actual superview).
Instead, you should transform coordinates to/from the correct coordinate system for each view.
Again, you've posted a lot of code, so I don't know what's going on in detail, and I might be on the wrong track here, but it does look kinda wrong to me.