Implement UIKitDynamics for dragging view off screen

后端 未结 3 1330
感动是毒
感动是毒 2020-12-22 16:36

I\'m trying to figure out implement UIKit Dynamics that are similar to those in Jelly\'s app (specifically swiping down to drag view off-screen).

See the animation:

3条回答
  •  一整个雨季
    2020-12-22 17:22

    SWIFT 3.0 :

    import UIKit
    
    class SwipeToDisMissView: UIView {
    
    var animator : UIDynamicAnimator?
    
    func initSwipeToDismissView(_ parentView:UIView)  {
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(SwipeToDisMissView.panGesture))
        self.addGestureRecognizer(panGesture)
        animator = UIDynamicAnimator(referenceView: parentView)
    }
    
    func panGesture(_ gesture:UIPanGestureRecognizer)  {
        var attachment : UIAttachmentBehavior?
        var lastTime = CFAbsoluteTime()
        var lastAngle: CGFloat = 0.0
        var angularVelocity: CGFloat = 0.0
    
        if gesture.state == .began {
            self.animator?.removeAllBehaviors()
            if let gestureView = gesture.view {
                let pointWithinAnimatedView = gesture.location(in: gestureView)
                let offset = UIOffsetMake(pointWithinAnimatedView.x - gestureView.bounds.size.width / 2.0, pointWithinAnimatedView.y - gestureView.bounds.size.height / 2.0)
                let anchor = gesture.location(in: gestureView.superview!)
                // create attachment behavior
                attachment = UIAttachmentBehavior(item: gestureView, offsetFromCenter: offset, attachedToAnchor: anchor)
                // code to calculate angular velocity (seems curious that I have to calculate this myself, but I can if I have to)
                lastTime = CFAbsoluteTimeGetCurrent()
                lastAngle = self.angleOf(gestureView)
                weak var weakSelf = self
                attachment?.action = {() -> Void in
                    let time = CFAbsoluteTimeGetCurrent()
                    let angle: CGFloat = weakSelf!.angleOf(gestureView)
                    if time > lastTime {
                        angularVelocity = (angle - lastAngle) / CGFloat(time - lastTime)
                        lastTime = time
                        lastAngle = angle
                    }
                }
                self.animator?.addBehavior(attachment!)
            }
        }
        else if gesture.state == .changed {
            if let gestureView = gesture.view {
                if let superView = gestureView.superview {
                    let anchor = gesture.location(in: superView)
                    if let attachment = attachment {
                        attachment.anchorPoint = anchor
                    }
                }
            }
        }
        else if gesture.state == .ended {
            if let gestureView = gesture.view {
                let anchor = gesture.location(in: gestureView.superview!)
                attachment?.anchorPoint = anchor
                self.animator?.removeAllBehaviors()
                let velocity = gesture.velocity(in: gestureView.superview!)
                let dynamic = UIDynamicItemBehavior(items: [gestureView])
                dynamic.addLinearVelocity(velocity, for: gestureView)
                dynamic.addAngularVelocity(angularVelocity, for: gestureView)
                dynamic.angularResistance = 1.25
                // when the view no longer intersects with its superview, go ahead and remove it
                weak var weakSelf = self
                dynamic.action = {() -> Void in
                    if !gestureView.superview!.bounds.intersects(gestureView.frame) {
                        weakSelf?.animator?.removeAllBehaviors()
                        gesture.view?.removeFromSuperview()
                    }
                }
                self.animator?.addBehavior(dynamic)
    
                let gravity = UIGravityBehavior(items: [gestureView])
                gravity.magnitude = 0.7
                self.animator?.addBehavior(gravity)
            }
        }
    }
    
    func angleOf(_ view: UIView) -> CGFloat {
        return atan2(view.transform.b, view.transform.a)
    }
    }
    

提交回复
热议问题