我不能使用UIButton IBAction后,向下动画。我尝试将它带到superview的顶层,使用
cardOneButton.superview?.bringToFront(cardOneButton)
这将按钮带到最上层,但我仍然无法使用按钮Tap触发IBAction。
我试过了
cardOneButton.isUserInteractionEnabled = true
但这个东西也不行。
cardOneButton是放置在视图中的按钮的IBOutlet的名称。
使按钮动画化的代码:
func animateCardOneButton(_ cardOneLabel: UIButton){
let startX = cardOneButton.frame.origin.x + (cardOneButton.frame.size.width / 2)
let startY = cardOneButton.frame.origin.y + (cardOneButton.frame.size.height / 2)
let endX = startX
let endY = startY + 280
let animation = baseAnimation(startX, startY, endX, endY)
cardOneButton.layer.add(animation, forKey: nil)
}
其中baseAnimation(:、:、:、:)定义为:
func baseAnimation(_ startX: CGFloat, _ startY: CGFloat, _ endX: CGFloat, _ endY: CGFloat) -> CABasicAnimation{
let animation = CABasicAnimation(keyPath: "position")
animation.fromValue = CGPoint(x: startX, y: startY)
animation.toValue = CGPoint(x: endX, y: endY)
animation.duration = 0.5
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
animation.beginTime = CACurrentMediaTime()
return animation
}
这里有一个简单的例子可以告诉你两者的区别...
它将是这样开始的:
你可以点击每一个红色按钮。
运行动画后会是这样的:
你将能够点击“点击我2”,因为我们动画它的框架而不是它的层。
你不能点击“点击我1”,因为我们动画了它的图层,但是...然后点击“Label 1”,您将看到“tap Me 1”按钮突出显示并调用其.TouchupInside
操作。
那是因为“标签1”显示的是“轻拍我1”的原始帧----而且那个帧还在那里!
class ViewController: UIViewController {
var cardOneButton: UIButton!
var cardTwoButton: UIButton!
var labelOne: UILabel!
var labelTwo: UILabel!
var runAnimButton: UIButton!
var infoLabel2: UILabel!
var infoLabel1: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
labelOne = UILabel()
labelOne.text = "Label 1"
labelOne.textAlignment = .center
labelOne.backgroundColor = .systemTeal
view.addSubview(labelOne)
labelTwo = UILabel()
labelTwo.text = "Label 2"
labelTwo.textAlignment = .center
labelTwo.backgroundColor = .systemTeal
view.addSubview(labelTwo)
infoLabel1 = UILabel()
infoLabel1.text = "Result:"
infoLabel1.textAlignment = .center
infoLabel1.backgroundColor = .yellow
infoLabel1.font = .systemFont(ofSize: 15.0)
view.addSubview(infoLabel1)
infoLabel2 = UILabel()
var s = ""
s += "Tap each red button...\n\n"
s += "Then tap the Animate button...\n\n"
s += "Then try to tap each red button...\n\n"
s += "AND try to Tap each Label"
infoLabel2.text = s
infoLabel2.textAlignment = .center
infoLabel2.numberOfLines = 0
infoLabel2.backgroundColor = .green
infoLabel2.font = .systemFont(ofSize: 14.0)
view.addSubview(infoLabel2)
cardOneButton = UIButton()
cardOneButton.backgroundColor = .systemRed
cardOneButton.setTitle("Tap Me 1", for: [])
cardOneButton.setTitleColor(.black, for: .highlighted)
view.addSubview(cardOneButton)
cardTwoButton = UIButton()
cardTwoButton.backgroundColor = .systemRed
cardTwoButton.setTitle("Tap Me 2", for: [])
cardTwoButton.setTitleColor(.black, for: .highlighted)
view.addSubview(cardTwoButton)
runAnimButton = UIButton()
runAnimButton.backgroundColor = .lightGray
runAnimButton.setTitle("Animate", for: [])
runAnimButton.setTitleColor(.black, for: .highlighted)
view.addSubview(runAnimButton)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
[runAnimButton, cardOneButton, cardTwoButton].forEach { b in
b.frame = CGRect(origin: .zero, size: CGSize(width: 120, height: 40))
}
runAnimButton.center.x = view.center.x
runAnimButton.frame.origin.y = view.safeAreaInsets.top + 20
cardOneButton.frame.origin = CGPoint(x: 40, y: runAnimButton.frame.maxY + 20)
cardTwoButton.frame.origin = CGPoint(x: cardOneButton.frame.maxX + 40, y: runAnimButton.frame.maxY + 20)
labelOne.frame = cardOneButton.frame
labelTwo.frame = cardTwoButton.frame
infoLabel1.frame = CGRect(x: 40, y: cardOneButton.frame.maxY + 20, width: 280, height: 30)
let sz = infoLabel2.systemLayoutSizeFitting(CGSize(width: 280, height: 300), withHorizontalFittingPriority: .required, verticalFittingPriority: .defaultLow)
infoLabel2.frame = CGRect(x: 40, y: infoLabel1.frame.maxY + 20, width: 280, height: sz.height + 16)
cardOneButton.addTarget(self, action: #selector(btnTapped(_:)), for: .touchUpInside)
cardTwoButton.addTarget(self, action: #selector(btnTapped(_:)), for: .touchUpInside)
runAnimButton.addTarget(self, action: #selector(doAnim(_:)), for: .touchUpInside)
}
@objc func btnTapped(_ sender: Any?) -> Void {
guard let b = sender as? UIButton,
let t = b.currentTitle
else { return }
infoLabel1.text = "Result: \(t) was tapped!"
}
@objc func doAnim(_ sender: Any?) -> Void {
// original LAYER animation
animateCardOneButton(cardOneButton)
// animate frame of BUTTON itself
animateButton(cardTwoButton)
}
func animateButton(_ aButton: UIButton) -> Void {
let startY = aButton.frame.origin.y
let endY = startY + 280
UIView.animate(withDuration: 0.5, animations: {
aButton.frame.origin.y = endY
})
}
func animateCardOneButton(_ aButton: UIButton){
let startX = aButton.frame.origin.x + (aButton.frame.size.width / 2)
let startY = aButton.frame.origin.y + (aButton.frame.size.height / 2)
let endX = startX
let endY = startY + 280
let animation = baseAnimation(startX, startY, endX, endY)
aButton.layer.add(animation, forKey: nil)
}
func baseAnimation(_ startX: CGFloat, _ startY: CGFloat, _ endX: CGFloat, _ endY: CGFloat) -> CABasicAnimation{
let animation = CABasicAnimation(keyPath: "position")
animation.fromValue = CGPoint(x: startX, y: startY)
animation.toValue = CGPoint(x: endX, y: endY)
animation.duration = 0.5
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
animation.beginTime = CACurrentMediaTime()
return animation
}
}