Skip to content

Instantly share code, notes, and snippets.

@aybekckaya
Created May 14, 2020 01:09
Show Gist options
  • Save aybekckaya/320eb8e244bceed368185f9a6a043fe7 to your computer and use it in GitHub Desktop.
Save aybekckaya/320eb8e244bceed368185f9a6a043fe7 to your computer and use it in GitHub Desktop.
// 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