Skip to content

Commit a17f8c4

Browse files
committed
prevent tap when animating and adjust some codes.
1 parent 890be5f commit a17f8c4

File tree

1 file changed

+131
-95
lines changed

1 file changed

+131
-95
lines changed

Sources/ImageViewerController.swift

Lines changed: 131 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate {
2525
return _parent.navBar
2626
}
2727

28+
// MARK: Layout Constraints
2829
private var top:NSLayoutConstraint!
2930
private var leading:NSLayoutConstraint!
3031
private var trailing:NSLayoutConstraint!
@@ -34,7 +35,8 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate {
3435
private var scrollView:UIScrollView!
3536

3637
private var lastLocation:CGPoint = .zero
37-
38+
private var isAnimating:Bool = false
39+
3840
init(sourceView:UIImageView? = nil) {
3941
super.init(nibName: nil, bundle: nil)
4042
self.sourceView = sourceView
@@ -104,46 +106,20 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate {
104106

105107
override func viewDidAppear(_ animated: Bool) {
106108
super.viewDidAppear(animated)
107-
guard animateOnDidAppear == true,
108-
let sourceFrame = sourceView?.frameRelativeToWindow()
109-
else {
110-
// No animation
111-
return
109+
guard animateOnDidAppear == true else {
110+
// skip animation
111+
return
112112
}
113-
114113
animateOnDidAppear = false
115-
116-
let dummyImageView:UIImageView = UIImageView(frame: sourceFrame)
117-
dummyImageView.clipsToBounds = true
118-
dummyImageView.contentMode = .scaleAspectFill
119-
dummyImageView.alpha = 1.0
120-
dummyImageView.image = imageView.image
121-
view.addSubview(dummyImageView)
122-
view.sendSubviewToBack(dummyImageView)
123-
124-
sourceView?.alpha = 1.0
125-
imageView.alpha = 0.0
126-
backgroundView?.alpha = 0.0
127-
128-
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {[weak self] in
129-
guard let _self = self else { return }
130-
UIView.animate(withDuration: 0.237, animations: {
131-
dummyImageView.contentMode = .scaleAspectFit
132-
dummyImageView.frame = _self.view.frame
133-
_self.backgroundView?.alpha = 1.0
134-
_self.sourceView?.alpha = 0.0
135-
}) { _ in
136-
_self.imageView.alpha = 1.0
137-
dummyImageView.removeFromSuperview()
138-
}
139-
}
114+
executeOpeningAnimation()
140115
}
141116

142117
override func viewWillLayoutSubviews() {
143118
super.viewWillLayoutSubviews()
144119
updateMinMaxZoomScaleForSize(view.bounds.size)
145120
}
146121

122+
// MARK: Add Gesture Recognizers
147123
func addGestureRecognizers() {
148124

149125
let panGesture = UIPanGestureRecognizer(
@@ -173,20 +149,13 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate {
173149
singleTapGesture.require(toFail: doubleTapRecognizer)
174150
}
175151

176-
func updateMinMaxZoomScaleForSize(_ size: CGSize) {
177-
let widthScale = size.width / imageView.bounds.width
178-
let heightScale = size.height / imageView.bounds.height
179-
let minScale = min(widthScale, heightScale)
180-
181-
scrollView.minimumZoomScale = minScale
182-
scrollView.zoomScale = minScale
183-
scrollView.maximumZoomScale = max(1, minScale) * 2
184-
}
185-
186152
@objc
187153
func didPan(_ gestureRecognizer: UIPanGestureRecognizer) {
154+
guard
155+
isAnimating == false,
156+
scrollView.zoomScale == scrollView.minimumZoomScale
157+
else { return }
188158

189-
if scrollView.minimumZoomScale != scrollView.zoomScale { return }
190159
let container:UIView! = imageView
191160
if gestureRecognizer.state == .began {
192161
lastLocation = container.center
@@ -204,45 +173,9 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate {
204173
backgroundView?.alpha = 1.0 - abs(diffY/view.center.y)
205174
if gestureRecognizer.state == .ended {
206175
if abs(diffY) > 60 {
207-
let dummyImageView:UIImageView = UIImageView(frame: container.frame)
208-
dummyImageView.image = imageView.image
209-
dummyImageView.clipsToBounds = false
210-
dummyImageView.contentMode = .scaleAspectFill
211-
view.addSubview(dummyImageView)
212-
imageView.isHidden = true
213-
214-
let exitFrame:CGRect = { () -> CGRect in
215-
guard let _sourceFrame = self.sourceView?.frameRelativeToWindow()
216-
else {
217-
var imageViewFrame = self.imageView.frame
218-
if diffY > 0 {
219-
imageViewFrame.origin.y = -imageViewFrame.size.height
220-
} else {
221-
imageViewFrame.origin.y = view.frame.size.height
222-
}
223-
return imageViewFrame
224-
}
225-
return _sourceFrame
226-
}()
227-
228-
UIView.animate(withDuration: 0.237, animations: {
229-
dummyImageView.frame = exitFrame
230-
dummyImageView.clipsToBounds = true
231-
self.backgroundView?.alpha = 0.0
232-
self.navBar?.alpha = 0.0
233-
}) { _ in
234-
self.dismiss(animated: false) {
235-
dummyImageView.removeFromSuperview()
236-
self.delegate?.imageViewerDidClose(self)
237-
}
238-
}
176+
executeViewDismissalAnimation(diffY)
239177
} else {
240-
UIView.animate(
241-
withDuration: 0.237,
242-
animations: {
243-
container.center = self.view.center
244-
self.backgroundView?.alpha = 1.0
245-
})
178+
executeCancelAnimation()
246179
}
247180
}
248181
}
@@ -268,18 +201,31 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate {
268201
let pointInView = recognizer.location(in: imageView)
269202
zoomInOrOut(at: pointInView)
270203
}
204+
205+
func gestureRecognizerShouldBegin(
206+
_ gestureRecognizer: UIGestureRecognizer) -> Bool {
207+
if let panGesture = gestureRecognizer as? UIPanGestureRecognizer {
208+
let velocity = panGesture.velocity(in: scrollView)
209+
return abs(velocity.y) > abs(velocity.x)
210+
}
211+
return false
212+
}
213+
}
214+
215+
// MARK: Adjusting the dimensions
216+
extension ImageViewerController {
271217

272-
func updateConstraintsForSize(_ size: CGSize) {
273-
let yOffset = max(0, (size.height - imageView.frame.height) / 2)
274-
top.constant = yOffset
275-
bottom.constant = yOffset
218+
func updateMinMaxZoomScaleForSize(_ size: CGSize) {
219+
let widthScale = size.width / imageView.bounds.width
220+
let heightScale = size.height / imageView.bounds.height
221+
let minScale = min(widthScale, heightScale)
276222

277-
let xOffset = max(0, (size.width - imageView.frame.width) / 2)
278-
leading.constant = xOffset
279-
trailing.constant = xOffset
280-
view.layoutIfNeeded()
223+
scrollView.minimumZoomScale = minScale
224+
scrollView.zoomScale = minScale
225+
scrollView.maximumZoomScale = max(1, minScale) * 2
281226
}
282227

228+
283229
func zoomInOrOut(at point:CGPoint) {
284230
let newZoomScale = scrollView.zoomScale == scrollView.minimumZoomScale
285231
? scrollView.maximumZoomScale : scrollView.minimumZoomScale
@@ -291,14 +237,102 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate {
291237
let rect = CGRect(x: x, y: y, width: w, height: h)
292238
scrollView.zoom(to: rect, animated: true)
293239
}
240+
241+
func updateConstraintsForSize(_ size: CGSize) {
242+
let yOffset = max(0, (size.height - imageView.frame.height) / 2)
243+
top.constant = yOffset
244+
bottom.constant = yOffset
245+
246+
let xOffset = max(0, (size.width - imageView.frame.width) / 2)
247+
leading.constant = xOffset
248+
trailing.constant = xOffset
249+
view.layoutIfNeeded()
250+
}
294251

295-
func gestureRecognizerShouldBegin(
296-
_ gestureRecognizer: UIGestureRecognizer) -> Bool {
297-
if let panGesture = gestureRecognizer as? UIPanGestureRecognizer {
298-
let velocity = panGesture.velocity(in: scrollView)
299-
return abs(velocity.y) > abs(velocity.x)
252+
}
253+
254+
// MARK: Animation Related stuff
255+
extension ImageViewerController {
256+
257+
private func executeOpeningAnimation() {
258+
259+
guard let _sourceView = sourceView else { return }
260+
261+
let dummyImageView:UIImageView = UIImageView(
262+
frame: _sourceView.frameRelativeToWindow())
263+
dummyImageView.clipsToBounds = true
264+
dummyImageView.contentMode = .scaleAspectFill
265+
dummyImageView.alpha = 1.0
266+
dummyImageView.image = imageView.image
267+
view.addSubview(dummyImageView)
268+
view.sendSubviewToBack(dummyImageView)
269+
270+
_sourceView.alpha = 1.0
271+
imageView.alpha = 0.0
272+
backgroundView?.alpha = 0.0
273+
isAnimating = true
274+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {[weak self] in
275+
guard let _self = self else { return }
276+
UIView.animate(withDuration: 0.237, animations: {
277+
dummyImageView.contentMode = .scaleAspectFit
278+
dummyImageView.frame = _self.view.frame
279+
_self.backgroundView?.alpha = 1.0
280+
_sourceView.alpha = 0.0
281+
}) { _ in
282+
_self.imageView.alpha = 1.0
283+
dummyImageView.removeFromSuperview()
284+
_self.isAnimating = false
285+
}
286+
}
287+
}
288+
289+
private func executeCancelAnimation() {
290+
self.isAnimating = true
291+
UIView.animate(
292+
withDuration: 0.237,
293+
animations: {
294+
self.imageView.center = self.view.center
295+
self.backgroundView?.alpha = 1.0
296+
}) {[weak self] _ in
297+
self?.isAnimating = false
298+
}
299+
}
300+
301+
private func executeViewDismissalAnimation(_ diffY:CGFloat) {
302+
isAnimating = true
303+
304+
let dummyImageView:UIImageView = UIImageView(frame: imageView.frame)
305+
dummyImageView.image = imageView.image
306+
dummyImageView.clipsToBounds = false
307+
dummyImageView.contentMode = .scaleAspectFill
308+
view.addSubview(dummyImageView)
309+
imageView.isHidden = true
310+
311+
let exitFrame:CGRect = { () -> CGRect in
312+
guard let _sourceFrame = self.sourceView?.frameRelativeToWindow()
313+
else {
314+
var imageViewFrame = self.imageView.frame
315+
if diffY > 0 {
316+
imageViewFrame.origin.y = -imageViewFrame.size.height
317+
} else {
318+
imageViewFrame.origin.y = view.frame.size.height
319+
}
320+
return imageViewFrame
321+
}
322+
return _sourceFrame
323+
}()
324+
325+
UIView.animate(withDuration: 0.237, animations: {
326+
dummyImageView.frame = exitFrame
327+
dummyImageView.clipsToBounds = true
328+
self.backgroundView?.alpha = 0.0
329+
self.navBar?.alpha = 0.0
330+
}) { _ in
331+
self.dismiss(animated: false) {
332+
dummyImageView.removeFromSuperview()
333+
self.delegate?.imageViewerDidClose(self)
334+
}
300335
}
301-
return false
302336
}
303337
}
304338

@@ -313,6 +347,8 @@ extension ImageViewerController:UIScrollViewDelegate {
313347
}
314348
}
315349

350+
351+
// MARK: Shortcuts
316352
extension ImageViewerController {
317353

318354
static func create(

0 commit comments

Comments
 (0)