让用户能够在临时 UIView 上向下滑动

Have User be able to Swipe Down on temporary UIView

我希望能够让用户向下滑动以关闭从底部进入的临时通知。

代码如下所示:

func showAnimationToast(...) {
    
        let toastView = UIView(frame: CGRect(x: 10, y: view.frame.size.height - view.safeAreaInsets.bottom, width: view.frame.size.width - 20, height: 60))
        ...
        toastView.tag = 1474
        
        let animationView = AnimationView(name: animationName)
        ...
        toastView.addSubview(animationView)
        
        let messageLabel = UILabel(frame: CGRect(x: toastView.frame.size.height, y: 5, width: toastView.frame.size.width - toastView.frame.size.height, height: 50))
        ...
        toastView.addSubview(messageLabel) 
        toastView.isUserInteractionAvailable = true

我尝试将 UISwipeGestureRecognizer 添加到 toastView,但从未成功。我什至尝试了简单的 UITapGestureRecognizer,但它仍然没有用。

这是我尝试过的:


        //Let Swipe Down Dismiss. Does not work
        let swipeDownGesture = UISwipeGestureRecognizer(target: self, action: #selector(dismissToast(_:)))
        swipeDownGesture.direction = .down
        toastView.addGestureRecognizer(swipeDownGesture)
        
        //Show animation
        UIView.animate(withDuration: 0.2, delay: 0, animations: {
            toastView.frame.origin.y = self.view.frame.size.height - self.view.safeAreaInsets.bottom - 70
        }, completion: {_ in
            animationView.play()
        })
        
        //Remove after specified time
        UIView.animate(withDuration: 0.2, delay: duration, animations: {
            toastView.center.y = self.view.frame.size.height + 50
        }, completion: {_ in
            toastView.removeFromSuperview()
        })
    }
    
    @objc func dismissToast(_ sender: UIGestureRecognizer) {
        print("dismiss")
        let toastView = view.subviews.filter { view in
            if view.tag == 1474 /*toastView*/ tag{
                return true
            }
            return false
        }.last!
        
        UIView.animate(withDuration: 0.2, delay: 0, animations: {
            toastView.center.y = self.view.frame.size.height + 50
        }, completion: {_ in
            toastView.removeFromSuperview()
        })
        
    }

问题似乎是在视图等待动画播放时(在“延迟”期间),它无法接收用户交互。

解决此问题的一种方法是不使用 delay 参数,而是使用 DispatchQueue.main.asyncAfter:

    UIView.animate(withDuration: 0.2, delay: 0, options: [.allowUserInteraction], animations: {
        toastView.frame.origin.y = self.view.frame.size.height - self.view.safeAreaInsets.bottom - 70
    }, completion: {_ in
        DispatchQueue.main.asyncAfter(deadline: .now() + duration + 0.2) {
            UIView.animate(withDuration: 0.2, delay: 0, animations: {
                toastView.center.y = self.view.frame.size.height + 50
            }, completion: {_ in
                toastView.removeFromSuperview()
            })
        }

    })