ios - 在 Swift 中显示微调器的动画按钮
问题描述
所以我想让一个按钮在按下时动画到一个圆圈,然后能够将按钮发送回它的原始状态。这是我当前的动画,如您所见,我已经完成了一半。
您也可以看到我在这里遇到了多个问题。首先,当我设置我的新约束时,X 约束不会将圆圈放在父视图的中间。然后我最初的想法是,当我调用重置函数时,我也会传递视图的原始约束,但这不起作用。
我的想法是,当我使用它时,我会放置一个 UIView,然后在该视图中放置按钮,这样我就可以操纵它的约束。如果我在 UIStackView 中放置一个按钮,也会出现这种情况。
这是我的代码,任何输入都会很棒
extension UIButton {
func animateWhileAwaitingResponse(showLoading: Bool, originalConstraints: [NSLayoutConstraint]) {
let spinner = UIActivityIndicatorView()
let constraints = [
NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: self.superview, attribute: .centerX, multiplier: 1, constant: 0),
NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 45),
NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 45),
NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: self.superview, attribute: .top, multiplier: 1, constant: 4),
NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: self.superview, attribute: .bottom, multiplier: 1, constant: 8),
NSLayoutConstraint(item: spinner, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: 0),
NSLayoutConstraint(item: spinner, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0),
NSLayoutConstraint(item: spinner, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 45),
NSLayoutConstraint(item: spinner, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 45)
]
if showLoading {
NSLayoutConstraint.deactivate(self.constraints)
self.translatesAutoresizingMaskIntoConstraints = false
spinner.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(spinner)
self.superview?.addConstraints(constraints)
spinner.color = .white
spinner.startAnimating()
UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseInOut, animations: {
self.setTitleColor(.clear, for: .normal)
self.layer.cornerRadius = 22.5
self.layoutIfNeeded()
}, completion: nil)
} else {
UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseInOut, animations: {
NSLayoutConstraint.deactivate(self.constraints)
self.setTitleColor(.white, for: .normal)
self.superview?.addConstraints(originalConstraints)
NSLayoutConstraint.activate(originalConstraints)
self.layer.cornerRadius = 0
for subview in self.subviews where subview is UIActivityIndicatorView {
subview.removeFromSuperview()
}
self.layoutIfNeeded()
}, completion: nil)
}
}
}
解决方案
我已将您的按钮扩展代码更新如下,即添加和删除动画约束。
extension UIButton {
func animateWhileAwaitingResponse(showLoading: Bool, originalConstraints: [NSLayoutConstraint]) {
let spinner = UIActivityIndicatorView()
spinner.isUserInteractionEnabled = false
// Constraints which will add in supper view
let constraints = [
NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: self.superview, attribute: .centerX, multiplier: 1, constant: 0),
NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: self.superview, attribute: .centerY, multiplier: 1, constant: 0),
NSLayoutConstraint(item: spinner, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: 0),
NSLayoutConstraint(item: spinner, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0),
NSLayoutConstraint(item: spinner, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 45),
NSLayoutConstraint(item: spinner, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 45)
]
// Constrains which will add in button
let selfCostraints = [
NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 45),
NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 45),
]
// Keeping this outside of condition due to adding constrains programatically.
self.translatesAutoresizingMaskIntoConstraints = false
spinner.translatesAutoresizingMaskIntoConstraints = false
if showLoading {
// Remove width constrains of button from superview
// Identifier given in storyboard constrains
self.superview?.constraints.forEach({ (constraint) in
if constraint.identifier == "buttonWidth" {
constraint.isActive = false
}
})
NSLayoutConstraint.deactivate(self.constraints)
self.addSubview(spinner)
self.superview?.addConstraints(constraints)
self.addConstraints(selfCostraints)
spinner.color = .white
spinner.startAnimating()
spinner.alpha = 0
UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseInOut, animations: {
self.setTitleColor(.clear, for: .normal)
self.layer.cornerRadius = 22.5
spinner.alpha = 1
self.layoutIfNeeded()
}, completion: nil)
} else {
UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseInOut, animations: {
for subview in self.subviews where subview is UIActivityIndicatorView {
subview.removeFromSuperview()
}
self.removeConstraints(selfCostraints)
NSLayoutConstraint.deactivate(self.constraints)
self.setTitleColor(.white, for: .normal)
self.superview?.addConstraints(originalConstraints)
NSLayoutConstraint.activate(originalConstraints)
self.layer.cornerRadius = 0
self.layoutIfNeeded()
}, completion: nil)
}
}
}
我为按钮添加了以下约束:
此外,添加了按钮宽度约束的标识符以从 super 中删除,这将从原始约束添加运行时。
然后我通过采用宽度约束的出口以编程方式更改按钮的宽度:
@IBOutlet weak var const_btnAnimation_width : NSLayoutConstraint!
内部viewDidLoad
方法
self.const_btnAnimation_width.constant = UIScreen.main.bounds.width - 40
其中 40 是前导和尾随空格的总和。
点击按钮
@IBAction func btnAnimationPressed(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
self.btnAnimation.animateWhileAwaitingResponse(showLoading: true, originalConstraints: sender.constraints)
} else {
self.btnAnimation.animateWhileAwaitingResponse(showLoading: false, originalConstraints: self.btnAnimationConstraints)
}
}
btnAnimationConstraints
数组NSLayoutConstraint
如下:
var btnAnimationConstraints = [NSLayoutConstraint]()
所以我只是在方法内部分配按钮的所有约束,viewDidAppear
如下所示:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.btnAnimationConstraints = self.btnAnimation.constraints
}
我希望这能帮到您。
输出:
推荐阅读
- spring-boot - mongo 中是否有像 hibernate.showSql 这样的功能来跟踪 mongodb 中的查询执行
- node.js - Facebook 营销 API 不适用于 App 令牌?
- visual-studio-code - 带有 VSCode 的 Eslint 插件找不到插件
- mariadb - Mysql 表排序规则改变
- reactjs - 按下按钮时如何使数字对应的图像显示而不是数字?
- mysql - 如何在一条记录中获取不同记录的两个字段Mysql
- c# - 反序列化 JSON 字符串列表以找到正确的模型
- queue - FlowFiles 卡在 NiFi 集群的队列中
- javascript - 为什么使用fabricjs 导出时图像质量非常低?
- ios - 动态添加的类不会快速响应