IOS-卡片抽屉效果
git地址:模仿豆瓣的卡片抽屉
模仿豆瓣APP的抽屉弹出效果,采用Swift5
####效果图如下
二. 实现步骤
1.主要通过UIPanGestureRecognizer和UIViewPropertyAnimator一起协作完成此效果。
2 通过UIPanGestureRecognizer的State进行相关的处理。
3.核心在于动画的暂停,根据释放手势时候,进行处理动画未完成的继续进行处理。
4.核心代码如下:
/// 手势触发处理
@objc private func panned(recognizer: UIPanGestureRecognizer) {
switch recognizer.state {
case .began: /// 开启动画,并暂停
startAnimation()
animator.pauseAnimation()
animationProgress = animator.fractionComplete
case .changed:
var fraction = -recognizer.translation(in: drawerView).y / closedTransform.ty
if isOpen { fraction *= -1 }
if animator.isReversed { fraction *= -1 } /// 是否是反方向
animator.fractionComplete = fraction + animationProgress
case .ended, .cancelled:
/// y 轴方向的速度
let yVelocity = recognizer.velocity(in: drawerView).y
/// 根据速度来判断是否关闭 (可以控制大于多少速度时关闭)
let shouldClose = yVelocity > 0
if yVelocity == 0 {
animator.continueAnimation(withTimingParameters: nil, durationFactor: 0)
break
}
if isOpen {
if !shouldClose && !animator.isReversed { animator.isReversed.toggle() }
if shouldClose && animator.isReversed { animator.isReversed.toggle() }
} else {
if shouldClose && !animator.isReversed { animator.isReversed.toggle() }
if !shouldClose && animator.isReversed { animator.isReversed.toggle() }
}
/// 动画剩余未完成的比例。(fractionComplete 动画已经完成的比例)
let fractionRemaining = 1 - animator.fractionComplete
/// 动画还需要移动多少距离才完成
let distanceRemaining = fractionRemaining * closedTransform.ty
if distanceRemaining == 0 {
animator.continueAnimation(withTimingParameters: nil, durationFactor: 0)
break
}
let relativeVelocity = min(abs(yVelocity) / distanceRemaining, 30)
let timingParameters = UISpringTimingParameters(damping: 0.8, response: 0.3, initialVelocity: CGVector(dx: 0, dy: relativeVelocity))
let preferredDuration = UIViewPropertyAnimator(duration: 0, timingParameters: timingParameters).duration
let durationFactor = CGFloat(preferredDuration / animator.duration)
animator.continueAnimation(withTimingParameters: timingParameters, durationFactor: durationFactor)
default:
break
}
}
主要核心在于手势状态变为 .ended 或者 .cancelled 时候如何去计算剩余动画,以及如何处理剩余,来产生对应的抽屉效果。
gitdemo连接:可下载运行查看Demo
同名仓库下还有许多App,如采用了高级动画的完整APP 天气预爆Demo。
以及一些关于底层相关的内容工具,欢迎大家使用看看。