This code is to expand a label by disabling the constraint which is keeping it at a max height of 54 to a full size. It works as it should but it jumps to the new y position straight away (without animating) and changes frame height after which makes it look like it jumps before animating
#IBOutlet var descriptionHeightConstraint: NSLayoutConstraint!
#IBAction func toggleFullDescription(_ sender: Any) {
if descriptionHeightConstraint.isActive {
self.layoutIfNeeded()
descriptionHeightConstraint.isActive = false
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut, animations: {
self.layoutIfNeeded()
}, completion: nil)
//seeMoreButton.setTitle("See less", for: .normal)
} else {
self.layoutIfNeeded()
descriptionHeightConstraint.isActive = true
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut, animations: {
self.layoutIfNeeded()
}, completion: nil)
//seeMoreButton.setTitle("See more", for: .normal)
}
}
Video of the issue
Related
I'm trying to animate the color of my UIButton Title Color using animateKeyframes but it does nothing except load the last state in the animation, in this case purpleText. I'm using the same code to animate button colors and a UIView background color without any issues.
I checked also changed the button to a custom button in Interface Builder but that didn't help either.
UIView.animateKeyframes(withDuration: 12, delay: 12, options: [.allowUserInteraction, .repeat, .autoreverse], animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.25, animations: {
self.infoButton.setTitleColor(blueText, for: UIControlState.normal)
})
UIView.addKeyframe(withRelativeStartTime: 0.2, relativeDuration: 0.25, animations: {
self.infoButton.setTitleColor(greenText, for: UIControlState.normal)
})
UIView.addKeyframe(withRelativeStartTime: 0.4, relativeDuration: 0.25, animations: {
self.infoButton.setTitleColor(yellowText, for: UIControlState.normal)
})
UIView.addKeyframe(withRelativeStartTime: 0.6, relativeDuration: 0.25, animations: {
self.infoButton.setTitleColor(redText, for: UIControlState.normal)
})
UIView.addKeyframe(withRelativeStartTime: 0.8, relativeDuration: 0.25, animations: {
self.infoButton.setTitleColor(purpleText, for: UIControlState.normal)
})
}, completion: nil)
Calling setTitleColor() inside the animation block doesn't work because UIView.animate only works on animatable properties, like infoButton.backgroundColor.
Unfortunately, button properties like tintColor aren't animatable. You also shouldn't directly access the button's titleLabel, which is nil for system buttons.
Instead, you can use UIView.transition with setTitleColor(). You can then put it inside a Timer... I usually don't like to use timers for animations, but I can't think of any other way.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let colors: [UIColor] = [.blue, .green, .yellow, .red, .purple]
var currentIndex = 0
_ = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
if colors.indices.contains(currentIndex) {
UIView.transition(with: self.infoButton, duration: 0.5, options: [.transitionCrossDissolve, .allowUserInteraction]) {
self.infoButton.setTitleColor(colors[currentIndex], for: .normal)
}
currentIndex += 1
} else {
currentIndex = 0
}
}
}
Result:
My goal is to build a custom cell that, when tapped, animates similar to Snapchat's. I have gotten the animation to work, but as a scroll more (after tap), the last selected cell continues to animate as I tap around the screen. Here's a video example
To get this animation, I am overriding the isSelected value in a custom cell class like so:
override var isSelected: Bool {
didSet {
if isSelected {
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
self.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
}, completion: { _ in
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
self.transform = CGAffineTransform(scaleX: 1, y: 1)
}, completion: nil)
})
}
}
}
Please help me figure out why the last selected cell continues to animate even after the correct animation is completed.
I'm trying to make that my button double its size using the UIView animation, but for some reason it is not working it the size goes right, but no animated.
The function that should animate the button resizing
Irrelevant code above
#objc func createButtonPressed(){
//Removes the bottom stack with buttons
if let stackButton = self.view.viewWithTag(50){
stackButton.removeFromSuperview()
}
//Add the button back with half ares size
bottomHolder.addSubview(rightButton)
rightButton.setImage(nil, for: .normal)
rightButton.addTarget(self, action: #selector(anima), for: .touchUpInside)
rightButton.topAnchor.constraint(equalTo: bottomHolder.topAnchor).isActive = true
rightButton.trailingAnchor.constraint(equalTo: bottomHolder.trailingAnchor).isActive = true
rightButton.bottomAnchor.constraint(equalTo: bottomHolder.bottomAnchor).isActive = true
}
#objc func anima(){
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
self.rightButton.leadingAnchor.constraint(equalTo: self.bottomHolder.leadingAnchor).isActive = true
self.rightButton.layoutIfNeeded()
}, completion: nil)
}
Irrelevant code below
try this one:
let buttonFinalWidth = UIScreen.main.bounds.width
DispatchQueue.main.async {
UIView.animate(withDuration: 5.0) {
self.rightButton.widthAnchor.constraint(equalToConstant: buttonFinalWidth).isActive = true
self.view.layoutIfNeeded()
}
}
My Problem
I'm trying do some animation with label using UIView.animate(..) when touchInside button . Everything still be OK until I added a line: "self?.confirm.setTitle("Đăng nhập", for: .normal). The animation doesn't work.
My Will
I want the yellow underline below Đăng Ký switch to below Đăng nhập.
It good when code is
#IBAction func signUpAction(_ sender:Any?){
if (signup == false){
signup = true
UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseIn], animations: {[weak self] in
self?.underlineSignup.center.x -= (self?.underlineSignup.bounds.width)!
self?.view.layoutIfNeeded()
}, completion: nil)
}
}
#IBAction func signInAction(_ sender:Any?){
if (signup == true){
signup = false
UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseIn], animations: {[weak self] in
self?.underlineSignup.center.x += (self?.underlineSignup.bounds.width)!
self?.view.layoutIfNeeded()
}, completion: nil)
}
}
It work
But when I add .setTitle
#IBAction func signUpAction(_ sender:Any?){
if (signup == false){
signup = true
UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseIn], animations: {[weak self] in
self?.underlineSignup.center.x -= (self?.underlineSignup.bounds.width)!
self?.confirm.setTitle("Đăng ký", for: .normal)
self?.view.layoutIfNeeded()
}, completion: nil)
}
}
#IBAction func signInAction(_ sender:Any?){
if (signup == true){
signup = false
UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseIn], animations: {[weak self] in
self?.underlineSignup.center.x += (self?.underlineSignup.bounds.width)!
self?.confirm.setTitle("Đăng nhập", for: .normal)
self?.view.layoutIfNeeded()
}, completion: nil)
}
}
It stuck, only the title of button confirm change, the underline doesn't move
Please anyone can explain this situation.
EDIT:
The animation working but it's destination is always the first place which under Đăng ký ( animation come from left or right of it, the result always first place )
I think I knew how it is. Because in setTitle has updateFrame Constraintlayout of view. I have a contraintlayout when build button.
When I setTitles it reset the view using constraint.
That's what I think about this.
Try putting 'setTitle' into completion.
UIView.animate(withDuration: 0.15, delay: 0, options: .curveLinear, animations: {
self?.underlineSignup.center.x -= (self?.underlineSignup.bounds.width)!
self?.view.layoutIfNeeded()
}){
//completion
self?.confirm.setTitle("Đăng ký", for: .normal)
}
I am trying to create an animation where I want to slide a uiview from right to left once parent UIViewController has loaded although I am able to display the view but the animation is not working. My code for animation:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
view.isOpaque = false
UIView.animate(withDuration: 1.0, delay: 1.0, options: .curveEaseOut, animations: {
self.contentXConstraint.constant = 500
self.contentXConstraint.constant = 80
}) { (status) in
}
}
I have displayed the parent view controller as presented viewcontroller:
present(navController, animated: false, completion: nil)
You forgot self.view.layoutIfNeeded()
self.contentXConstraint.constant = 500
self.contentXConstraint.constant = 80
UIView.animate(withDuration: 1.0, delay: 1.0, options: .curveEaseOut, animations: {
self.view.layoutIfNeeded()
}) { (status) in
}
from https://developer.apple.com/documentation/uikit/uiview/1622507-layoutifneeded
Use this method to force the view to update its layout immediately. When using Auto Layout, the layout engine updates the position of views as needed to satisfy changes in constraints
Move your animation code from viewDidAppear to viewDidLayoutSubviews
You need to add layoutIfNeeded() method after updating constraints
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
view.isOpaque = false
UIView.animate(withDuration: 1.0, delay: 1.0, options: .curveEaseOut, animations: {
self.contentXConstraint.constant = 500
self.contentXConstraint.constant = 80
self.view.layoutIfNeeded()
}) { (status) in
}
}