控制器中懒加载的 containerView
class QianDaoCalendarSheet: UIViewController {
lazy var containerView: SpringView = {
let view = SpringView()
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
initialUI()
makePanGesture()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
/// 遵守协议 `PanGestureViewProtocol`
extension QianDaoCalendarSheet: PanGestureViewProtocol {
typealias View = SpringView
var targetView: SpringView {
self.containerView
}
var targetViewHeight: CGFloat {
490
}
var autoDismissHeight: CGFloat? {
300
}
var duration: CGFloat? {
0.2
}
func downAnimationCompleted() {
// dismiss viewController
self.dismiss(animated: true)
}
func makePanGesture() {
let panGes = UIPanGestureRecognizer.init()
containerView.addGestureRecognizer(panGes)
panGes.addTarget(self, action: #selector(handlerPanGesture(sender:)))
}
@objc func handlerPanGesture(sender: UIPanGestureRecognizer) {
panGestureAction(pan: sender)
}
}
PanGestureViewProtocol 代码
protocol PanGestureViewProtocol {
associatedtype View: UIView
/// 滑动的view
var targetView: View { get }
/// view高度
var targetViewHeight: CGFloat { get }
/// view显示的高度,小于此高度,view会自动收起
var autoDismissHeight: CGFloat? { get }
/// 动画时间
var duration: CGFloat? { get }
/// targetView 动画完成后调用
func downAnimationCompleted()
}
extension PanGestureViewProtocol {
public func panGestureAction(pan: UIPanGestureRecognizer) {
let translation = pan.translation(in: self.targetView)
let height = targetViewHeight - translation.y
if translation.y < 0 {
return
} else {
let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
let SCREEN_WIDTH = UIScreen.main.bounds.size.width
self.targetView.frame = CGRect(x: 0, y: SCREEN_HEIGHT-height, width: SCREEN_WIDTH, height: targetViewHeight)
switch pan.state {
case .began:
break
case .ended:
if height < autoDismissHeight ?? targetViewHeight*0.5, height > 0 {
moveToDown(targetView)
} else if height >= autoDismissHeight ?? targetViewHeight*0.5, height <= targetViewHeight {
moveToUp(targetView)
} else if height <= 0 {
targetView.frame = CGRect(x: 0, y: SCREEN_HEIGHT, width: SCREEN_WIDTH, height: targetViewHeight)
} else {
targetView.frame = CGRect(x: 0, y: SCREEN_HEIGHT-targetViewHeight, width: SCREEN_WIDTH, height: targetViewHeight)
}
default:
break
}
}
}
private func moveToUp(_ targetView: View) {
let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
let SCREEN_WIDTH = UIScreen.main.bounds.size.width
UIView.animate(withDuration: duration ?? 0.2, delay: 0, options: .curveLinear) {
targetView.frame = CGRect(x: 0, y: SCREEN_HEIGHT - targetViewHeight, width: SCREEN_WIDTH, height: targetViewHeight)
} completion: { _ in }
}
private func moveToDown(_ targetView: View) {
let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
let SCREEN_WIDTH = UIScreen.main.bounds.size.width
UIView.animate(withDuration: duration ?? 0.2, delay: 0, options: .curveLinear) {
targetView.frame = CGRect(x: 0, y: SCREEN_HEIGHT, width: SCREEN_WIDTH, height: targetViewHeight)
} completion: { finished in
if finished {
downAnimationCompleted()
} else { }
}
}
}
效果实现在 智能教辅 v3.1.2以后版本可查看,(首页->签到->点击日历)