IOS-卡片抽屉效果

24 篇文章 0 订阅
22 篇文章 0 订阅

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

以及一些关于底层相关的内容工具,欢迎大家使用看看。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值