美文网首页
iOS Swift 给动画添加点击事件

iOS Swift 给动画添加点击事件

作者: rome753 | 来源:发表于2022-04-20 13:42 被阅读0次
    image.png

    当前View里面有两个View,绿色的bigView和红色的smallView,smallView在bigView里面。现在让bigView执行一段移动动画,然后给bigView添加点击事件,发现点击事件无效。

    因为iOS动画中的View点击事件无效

    原因是iOS里几乎所有的View动画是都基于layer实现的,frame在动画开始会直接变成终点状态。动画过程中bigView的frame不会变化,也不能接收点击事件。添加点击事件可以在bigView的父view也就是当前view中重写touchesBegan() 方法,判断点击位置在哪个view里面。

    添加完touchesBegan(),会发现点击bigView动画这个方法并不会触发,原因是动画中的layer会屏蔽触摸事件。这时有两种方法(效果相同):

    • 给UIView.animate() 方法添加options: .allowUserInteraction参数
    • 设置bigView的isUserInteractionEnabled = false

    这样点击事件就会传递给当前view

    class OurView: UIView {
        
        lazy var bigView = UIView(frame: CGRect(x: 100, y: 200, width: 200, height: 200))
        
        lazy var smallView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            backgroundColor = .white
            
            bigView.backgroundColor = .green
            addSubview(bigView)
            
            smallView.backgroundColor = .red
            bigView.addSubview(smallView)
            
            let tap = UITapGestureRecognizer(target: self, action: #selector(doClick))
            bigView.isUserInteractionEnabled = true
            bigView.addGestureRecognizer(tap)
            
            UIView.animate(withDuration: 100, delay: 0, options: .allowUserInteraction) {
                self.bigView.transform = CGAffineTransform(translationX: 0, y: 300)
            } completion: { _ in
    
            }
    
        }
        
        @objc func doClick() {
            print("clicked")
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    

    接下来判断点击位置在哪个View里。
    touch.location(in: self)获取触摸点在当前view中的位置;用bigView.layer.presentation()?.frame可以获取动画中的layer的frame。

    • 如果要判断是否点击了bigView,直接用movingFrame.contains(point)即可。
    • 如果要判断是否点击了smallView,也就是动画中的view的子view,那么需要进行坐标转换才能得到smallView的实时frame:用offsetBy方法转换smallView.frame,最后用smallFrame.contains(point)判断:
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            for touch in touches {
                var point = touch.location(in: self)
                if let movingFrame = bigView.layer.presentation()?.frame {
                    let f = smallView.frame
                    var smallFrame = f.offsetBy(dx: movingFrame.minX, dy: movingFrame.minY)
                    let contains = smallFrame.contains(point)
                    print("smallView touches: \(contains)")
                }
                break;
        }
    

    相关文章

      网友评论

          本文标题:iOS Swift 给动画添加点击事件

          本文链接:https://www.haomeiwen.com/subject/wocvertx.html