使用 SnapKit 约束动画
Posted
技术标签:
【中文标题】使用 SnapKit 约束动画【英文标题】:Constraint animation with SnapKit 【发布时间】:2018-06-01 19:45:53 【问题描述】:我正在尝试使用 SnapKit 实现 2 个视图的动画。
这是我的动画视图:
class MatchAnimation: UIView
let viewBackground: UIView =
let view = UIView()
view.backgroundColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 0.75)
view.alpha = 1
return view
()
let matchView: UIView =
let view = UIView()
return view
()
let matchLabel: UILabel =
let label = UILabel()
label.text = "Title"
label.textColor = .white
label.textAlignment = .center
return label
()
let leftAvatarBg: UIView =
let view = UIView()
view.backgroundColor = .white
view.layer.cornerRadius = 91/2
return view
()
let rightAvatarBg: UIView =
let view = UIView()
view.backgroundColor = .blue
view.layer.cornerRadius = 91/2
return view
()
let goToChatButton: UIButton =
let button = UIButton()
button.setTitle("Button", for: .normal)
button.backgroundColor = .red
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 24.5
return button
()
init()
super.init(frame: UIScreen.main.bounds)
viewBackground.frame = self.frame
self.addSubview(viewBackground)
self.addSubview(matchView)
matchView.addSubview(matchLabel)
matchView.addSubview(leftAvatarBg)
matchView.addSubview(rightAvatarBg)
matchView.addSubview(goToChatButton)
matchView.snp.makeConstraints (make) in
make.left.right.equalToSuperview()
make.center.equalToSuperview()
matchLabel.snp.makeConstraints (make) in
make.top.equalToSuperview()
make.centerX.equalToSuperview()
make.size.equalTo(CGSize(width: 193, height: 40))
leftAvatarBg.snp.makeConstraints (make) in
make.top.equalTo(matchLabel.snp.bottom).offset(20)
make.size.equalTo(CGSize(width: 91, height: 91))
make.right.equalTo(self.snp.left).offset(0)
rightAvatarBg.snp.makeConstraints (make) in
make.top.equalTo(leftAvatarBg)
make.size.equalTo(leftAvatarBg)
make.left.equalTo(self.snp.right).inset(0)
goToChatButton.snp.makeConstraints (make) in
make.size.equalTo(CGSize(width: 171, height: 50))
make.top.equalTo(leftAvatarBg.snp.bottom).offset(25)
make.centerX.equalToSuperview()
make.bottom.equalToSuperview()
func animate()
UIView.animate(withDuration: 5)
self.leftAvatarBg.snp.updateConstraints (make) in
make.right.equalTo(self.snp.left).offset(UIScreen.main.bounds.width/2+30)
self.rightAvatarBg.snp.updateConstraints (make) in
make.left.equalTo(self.snp.right).inset(UIScreen.main.bounds.width/2+30)
self.layoutIfNeeded()
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
我尝试制作动画的 2 个视图是 leftAvatarBg 和 rightAvatarBg。
在动画之前,我将它们设置在屏幕的外部,想让它们在一个视图中从左向右滑动,在另一个视图中从右向左滑动。
在我的控制器中,我只是调用:
func setupAnimation()
let matchView = MatchAnimation()
view.addSubview(matchView)
matchView.animate()
这样做的结果是整个视图都在动画(缩放)。
我错过了什么吗?
更新:感谢 swift2geek,它们似乎是对象的创建和动画之间的冲突。在他的解决方案中,他通过按下按钮来触发动画。就我而言,我想尽快自动触发动画。如何确保在创建对象后触发动画?
【问题讨论】:
尝试将 2 个更新块放在动画之外,只保留 layoutIfNeded() 我试过了,结果是一样的 你能把动画线放在 viewDidAppear 中吗,同样在 setupAnimation 中,在添加子视图之前看不到 frame 或 aulayout 只需更改约束并调用:UIView.animate(withDuration: 0.01, animations: [weak self] in self?.view.layoutIfNeeded() )
【参考方案1】:
我对您的 bdsm SnapKit 不满意,因此请自行设置正确的限制。所以它不起作用的主要原因 - 你应该分开动画和对象创建。
你的视图控制器:
import UIKit
class ViewController: UIViewController
@IBOutlet var matchButton: MatchButton!
@IBOutlet var matchView: MatchAnimation!
override func viewDidLoad()
super.viewDidLoad()
setupAnimation()
setupButton()
func setupAnimation()
matchView = MatchAnimation()
matchView.isUserInteractionEnabled = true
view.addSubview(matchView)
func setupButton()
matchButton = MatchButton()
matchButton.isUserInteractionEnabled = true
matchButton.isEnabled = true
matchButton.addTarget(self, action: #selector(pressed(_:)), for: .touchUpInside)
matchView.addSubview(matchButton)
@objc func pressed(_ sender: MatchButton!)
print("button tapped")
matchView.animate()
你的 MatchAnimation 类:
import UIKit
import SnapKit
class MatchAnimation: UIView
let viewBackground: UIView =
let view = UIView()
view.backgroundColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 0.75)
view.alpha = 1
return view
()
let matchView: UIView =
let view = UIView()
return view
()
let matchLabel: UILabel =
let label = UILabel()
label.text = "Title"
label.textColor = .white
label.textAlignment = .center
return label
()
let leftAvatarBg: UIView =
let view = UIView()
view.backgroundColor = .white
view.layer.cornerRadius = 91/2
return view
()
let rightAvatarBg: UIView =
let view = UIView()
view.backgroundColor = .blue
view.layer.cornerRadius = 91/2
return view
()
init()
super.init(frame: UIScreen.main.bounds)
viewBackground.frame = self.frame
self.addSubview(viewBackground)
self.addSubview(matchView)
matchView.addSubview(matchLabel)
matchView.addSubview(leftAvatarBg)
matchView.addSubview(rightAvatarBg)
matchView.snp.makeConstraints (make) in
make.left.right.equalToSuperview()
make.center.equalToSuperview()
matchLabel.snp.makeConstraints (make) in
make.top.equalToSuperview()
make.centerX.equalToSuperview()
make.size.equalTo(CGSize(width: 193, height: 40))
leftAvatarBg.snp.makeConstraints (make) in
make.top.equalTo(matchLabel.snp.bottom).offset(20)
make.centerX.equalToSuperview()
make.size.equalTo(CGSize(width: 91, height: 91))
make.right.equalTo(self.snp.left).offset(90)
rightAvatarBg.snp.makeConstraints (make) in
make.top.equalTo(leftAvatarBg)
make.size.equalTo(leftAvatarBg)
make.left.equalTo(self.snp.right).inset(120)
func animate()
UIView.animate(withDuration: 5)
self.leftAvatarBg.snp.updateConstraints (make) in
make.right.equalTo(self.snp.left).offset(UIScreen.main.bounds.width/2+30)
self.rightAvatarBg.snp.updateConstraints (make) in
make.left.equalTo(self.snp.right).inset(UIScreen.main.bounds.width/2+30)
self.layoutIfNeeded()
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
和匹配按钮:
import UIKit
import SnapKit
class MatchButton: UIButton
let goToChatButton: UIButton =
let button = UIButton()
button.setTitle("Button", for: .normal)
button.backgroundColor = .red
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 24.5
return button
()
init()
super.init(frame: UIScreen.main.bounds)
self.addSubview(goToChatButton)
goToChatButton.snp.makeConstraints (make) in
make.size.equalTo(CGSize(width: 171, height: 50))
make.top.greaterThanOrEqualTo(100)
make.centerX.equalToSuperview()
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
【讨论】:
为您解答。您似乎是对的,动画和视图的创建之间存在冲突。我尝试了您的解决方案并且它有效。问题是我不想通过按下按钮来触发动画,而是尽快自动触发。我怎样才能得到这个?我已经更新了我的问题【参考方案2】:如果您希望动画尽快触发,只需将布局animate()
函数添加到viewDidAppear
。
【讨论】:
以上是关于使用 SnapKit 约束动画的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 swift 3 的 snapkit 向任何 UI 添加动画?