gpt4 book ai didi

ios - 在运行的动画中检索点击的 UIButton,它可以稍微离开屏幕

转载 作者:搜寻专家 更新时间:2023-10-31 22:41:14 25 4
gpt4 key购买 nike

这就是代码(下面)的样子:

import UIKit

class TornadoButton: UIButton {

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let pres = self.layer.presentation()!
let suppt = self.convert(point, to: self.superview!)
let prespt = self.superview!.layer.convert(suppt, to: pres)

return super.hitTest(prespt, with: event)
}
}

class TestViewController: UIViewController {

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

let greySubview = UIView()
greySubview.backgroundColor = .red
greySubview.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(greySubview)

greySubview.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
greySubview.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
greySubview.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
greySubview.heightAnchor.constraint(equalTo: greySubview.widthAnchor).isActive = true

let button = TornadoButton()
greySubview.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
button.widthAnchor.constraint(equalTo: greySubview.widthAnchor, multiplier: 0.09).isActive = true
button.heightAnchor.constraint(equalTo: greySubview.heightAnchor, multiplier: 0.2).isActive = true

//below constrains are needed, else the origin of the UIBezierPath is wrong
button.centerXAnchor.constraint(equalTo: greySubview.centerXAnchor).isActive = true
button.centerYAnchor.constraint(equalTo: greySubview.centerYAnchor, constant: self.view.frame.height * 0.35).isActive = true
self.view.layoutIfNeeded()

button.addTarget(self, action: #selector(tappedOnCard(_:)), for: .touchUpInside)

let circlePath = UIBezierPath(arcCenter: greySubview.frame.origin, radius: CGFloat(greySubview.frame.width * 0.5), startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)

let orbit = CAKeyframeAnimation(keyPath: "position")
orbit.duration = 12
orbit.path = circlePath.cgPath
orbit.isAdditive = true
orbit.repeatCount = Float.greatestFiniteMagnitude
orbit.calculationMode = kCAAnimationPaced
orbit.rotationMode = kCAAnimationRotateAuto

button.layer.add(orbit, forKey: "orbit")
button.backgroundColor = .blue

let gr = UITapGestureRecognizer(target: self, action: #selector(onTap(gesture:)))
greySubview.addGestureRecognizer(gr)
}

@objc func onTap(gesture:UITapGestureRecognizer) {
let p = gesture.location(in: gesture.view)
let v = gesture.view?.hitTest(p, with: nil)
}

@IBAction func tappedOnCard(_ sender: UIButton) {
print(sender)
}
}

这几乎可以工作,但是:

如果按钮在屏幕上 100% 可见,我可以检索按钮。例如,如果 50% 可见(并且 50% 离开屏幕(见下图)),我不会检索按钮点击(也不会检索打印)。

当按钮处于正在运行的动画中并且它可以稍微离开屏幕时,如何检索按钮?

enter image description here

最佳答案

原始答案:

很可能是 greySubview 中的 UITapGestureRecognizer 正在消耗触摸,而不是让它传递到按钮。试试这个:

gr.cancelsTouchesInView = NO;

在将 UITapGestureRecognizer 添加到 greySubview 之前。


编辑后的答案:

请忽略我之前的回答,如果您这样做了,请恢复更改。我最初的回答没有意义,因为在您的情况下,按钮是 grayView 的 subview ,而 cancelsTouchesInView 在 View 层次结构中向上工作,而不是向下工作。

经过大量挖掘,我能够弄清楚为什么会这样。这是因为在动画期间 TornadoButton 中的 HitTest 不正确。由于您正在为按钮设置动画,因此您需要覆盖 TornadoButtonhitTestpointInside 方法,以便它们说明动画位置而不是点击测试时按钮的实际位置。

pointInside 方法的默认实现不考虑按钮的动画表示层,而只是尝试检查矩形内的触摸点(这将失败,因为触摸是别的地方)。

这些方法的以下实现似乎可以解决问题:

class TornadoButton: UIButton{
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let pres = self.layer.presentation()!
let suppt = self.convert(point, to: self.superview!)
let prespt = self.superview!.layer.convert(suppt, to: pres)
if (pres.hitTest(suppt)) != nil{
return self
}
return super.hitTest(prespt, with: event)
}

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
let pres = self.layer.presentation()!
let suppt = self.convert(point, to: self.superview!)
return (pres.hitTest(suppt)) != nil
}
}

关于ios - 在运行的动画中检索点击的 UIButton,它可以稍微离开屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46391003/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com