Instantly share code, notes, and snippets.
Created
May 14, 2020 01:09
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save aybekckaya/320eb8e244bceed368185f9a6a043fe7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MARK: Show / Hide | |
extension InteractiveMenu { | |
@objc fileprivate func blurViewDidTapped() { | |
self.hideView() | |
} | |
@objc fileprivate func containerViewPanned(recognizer: UIPanGestureRecognizer) { | |
switch recognizer.state { | |
case .began: | |
self.animator.stopAnimation(false) //1 | |
case .changed: | |
let currentTranslation = recognizer.translation(in: recognizer.view!) | |
self.setContainerViewCenter(currentTranslation: currentTranslation) | |
self.setBlurViewAlpha() | |
recognizer.setTranslation(CGPoint.zero, in: recognizer.view!) | |
case .ended , .cancelled: | |
let velocity = recognizer.velocity(in: recognizer.view!).y //2 | |
let distance = self.distanceForVelocity(velocity: velocity) | |
var prefferedVelocity = velocity / distance | |
if prefferedVelocity < 0 { prefferedVelocity = max(-30 , prefferedVelocity) } | |
let diffOpenYPos:CGFloat = abs(recognizer.view!.frame.origin.y - self.frameOpenPosition.origin.y) | |
let diffCloseYPos:CGFloat = abs(recognizer.view!.frame.origin.y - self.frameClosedPosition.origin.y) | |
let velocityTreshold:CGFloat = 0.5 //3 | |
if abs(prefferedVelocity) <= velocityTreshold && diffOpenYPos <= diffCloseYPos { | |
self.showView() | |
} | |
else if abs(prefferedVelocity) <= velocityTreshold && diffOpenYPos > diffCloseYPos { | |
self.hideView() | |
} | |
else if abs(prefferedVelocity) > velocityTreshold && prefferedVelocity < 0 { | |
let velocityValue = velocity * 0.01 | |
self.showView(initialVelocity: velocityValue) | |
} | |
else if abs(prefferedVelocity) > velocityTreshold && prefferedVelocity >= 0 { | |
let velocityValue = velocity * 0.01 | |
self.hideView(initialVelocity: velocityValue) | |
} | |
else { | |
self.showView() | |
} | |
default: break | |
} | |
} | |
//4 | |
private func applyRubberBandingIfNeeded(currentTranslation: CGPoint)->Bool { | |
let yPosNext = self.containerView.center.y + currentTranslation.y | |
let openedCenterYPos:CGFloat = self.frameOpenPosition.origin.y + self.frameOpenPosition.size.height / 2 | |
let closedCenterYPos:CGFloat = self.frameClosedPosition.origin.y + self.frameClosedPosition.size.height / 2 | |
guard yPosNext < openedCenterYPos || yPosNext > closedCenterYPos else { return false } | |
let translationY = currentTranslation.y * 0.05 | |
self.containerView.center = CGPoint(x: self.containerView.center.x, y: self.containerView.center.y + translationY) | |
return true | |
} | |
private func setContainerViewCenter(currentTranslation: CGPoint) { | |
guard self.applyRubberBandingIfNeeded(currentTranslation: currentTranslation) else { | |
self.containerView.center = CGPoint(x: self.containerView.center.x, y: self.containerView.center.y + currentTranslation.y) | |
return | |
} | |
} | |
private func setBlurViewAlpha() { | |
let openPosDistance:CGFloat = self.containerView.frame.origin.y - self.frameOpenPosition.origin.y | |
let maxDistance:CGFloat = self.frameClosedPosition.origin.y - self.frameOpenPosition.origin.y | |
let rateOpened:CGFloat = openPosDistance / maxDistance | |
let blurViewAlpha:CGFloat = min(0.7, 1-rateOpened) | |
self.viewBlurBackground.alpha = blurViewAlpha | |
} | |
//5 | |
private func distanceForVelocity(velocity:CGFloat)->CGFloat { | |
let openedCenterYPos:CGFloat = self.frameOpenPosition.origin.y + self.frameOpenPosition.size.height / 2 | |
let closedCenterYPos:CGFloat = self.frameClosedPosition.origin.y + self.frameClosedPosition.size.height / 2 | |
if velocity < 0 { return abs(openedCenterYPos - self.containerView.center.y) } | |
return abs(closedCenterYPos - self.containerView.center.y) | |
} | |
fileprivate func showView(initialVelocity: CGFloat = 0 ) { | |
if self.animator.isRunning { self.animator.stopAnimation(true) } | |
self.frame = CGRect(x: self.frame.origin.x, y: 0, width: self.frame.size.width, height: self.frame.size.height) | |
self.viewBlurBackground.alpha = 0.7 | |
//6 | |
let timingParameters = UISpringTimingParameters(damping: self.dampingValue, response: self.responseValue , initialVelocity: CGVector(dx: initialVelocity, dy: initialVelocity)) | |
self.animator = UIViewPropertyAnimator(duration: 0, timingParameters: timingParameters ) | |
self.animator.addAnimations { | |
self.containerView.frame = self.frameOpenPosition | |
} | |
self.animator.addCompletion { pos in | |
guard pos == .end else { return } | |
// fire delegate | |
} | |
self.animator.startAnimation() | |
} | |
fileprivate func hideView(initialVelocity: CGFloat = 0) { | |
if self.animator.isRunning { self.animator.stopAnimation(true) } | |
print("Velocity : \(initialVelocity)") | |
let timingParameters = UISpringTimingParameters(damping: self.dampingValue, response: self.responseValue , initialVelocity: CGVector(dx: initialVelocity, dy: initialVelocity)) | |
self.animator = UIViewPropertyAnimator(duration: 0, timingParameters: timingParameters ) | |
self.animator.addAnimations { | |
self.containerView.frame = self.frameClosedPosition | |
self.viewBlurBackground.alpha = 0 | |
} | |
self.animator.addCompletion { pos in | |
guard pos == .end else { return } | |
self.frame = CGRect(x: self.frame.origin.x, y: self.frame.size.height, width: self.frame.size.width, height: self.frame.size.height) | |
// fire delegate | |
} | |
self.animator.startAnimation() | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment