UIView animation jumps at beginning
I had the exact same problem so here is the solution I came up with.
CGAffineTransform transform = CGAffineTransformMake(1, 0, 0, 1, translation.x, translation.y);
[UIView animateWithDuration:0.25 animations:^{
_assetImageView.transform = transform;
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
}];
So I call [self.view layoutIfNeeded]; inside of the animate block. Without this the it has the same problem as you and jumps the distance negative translation first then animates to the correct position from there. I am calling this from a view controller so self is a sub class of UIViewController. In your case "self.view" may not exist but I hope you get the idea.
iOS Swift UIView animation jumps back to the beginning
You need to layout subview in Animation like this
self.skull_xConstraint.constant = xSkull
self.skull_yConstraint.constant = ySkull
UIView.animate(withDuration: 1.0, delay: 0.0, options: .curveEaseInOut, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
UIView animated position jumping
Just incase people don't want to read through the wall of text to find the solution the problem was that I was using the positions of views in different view controllers before all views had been laid out. I'd assumed that the entire view lifecycle had processed in my presenting view controller before the animation logic started, I was wrong.
Animation Call Order:
- viewDidLoad
- viewWillAppear
- animateTransition
- viewWillLayoutSubviews
- viewDidLayoutSubviews
So the fix was to manually call setNeedsLayout()
and layoutIfNeeded()
as the start of my animateTransition so that the positions of my views were all known and could be used for transformations.
Animated UIView object jumps when touchesBegan is invoked
You need to remove/reset the animation after you change the location of the label. The animation does not know you updated the values and is trying to stay in the same range of byValue from the beginning. Here is a working example of updating the animation.
import UIKit
class ViewController: UIViewController {
var optOneLbl = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
optOneLbl = UILabel(frame: CGRect(x: 20, y: 50, width: self.view.bounds.width - 40, height: 40))
optOneLbl.textAlignment = .center
optOneLbl.text = "I Will Be Moving Up and Down"
optOneLbl.textColor = .white
optOneLbl.backgroundColor = .blue
self.view.addSubview(optOneLbl)
//starts it in the beginnning with a y
fireAnimation(toY: self.view.bounds.midY*1.1)
}
func fireAnimation(toY:CGFloat) {
UIView.animate(withDuration: 12.0, delay: 0.0, options: [ .allowUserInteraction, .curveLinear, .autoreverse, .repeat ], animations: {
self.optOneLbl.center = CGPoint(x: self.optOneLbl.center.x, y:toY)
})
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self.view)
if self.optOneLbl.layer.presentation()!.hitTest(touchLocation) != nil {
//re
optOneLbl.layer.removeAllAnimations()
optOneLbl.center = touchLocation
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self.view)
var sender: UILabel
if self.optOneLbl.layer.presentation()!.hitTest(touchLocation) != nil {
self.optOneLbl.center = touchLocation
sender = self.optOneLbl
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
//restart animation after finished and change the Y if you want.
// you could change duration or whatever
fireAnimation(toY: self.view.bounds.height - optOneLbl.bounds.height)
}
}
Height constraint animation 'jumping'
UIView.animate()
can be a little tricky -- you need to call .layoutIfNeeded()
on the correct view.
Replace your isExpanded / didSet
in iDUMenuButton
class with this:
var isExpanded = false {
didSet {
if isExpanded != oldValue {
if isExpanded {
becomeFirstResponder()
let haptics = UIImpactFeedbackGenerator(style: .rigid)
haptics.impactOccurred()
}
guard let sv = self.superview else {
// shouldn't happen, but let's be thorough
fatalError("Self must have a superview!!!")
}
// not needed
//self.layoutIfNeeded()
UIView.animate(withDuration: 0.3) {
self.heightConstraint.isActive = !self.isExpanded
// call .layoutIfNeeded() on self's superview
//self.layoutIfNeeded()
sv.layoutIfNeeded()
self.layer.shadowOpacity = self.isExpanded ? 1 : 0
self.buttons.forEach { $0.setBadgeHidden(hidden: !self.isExpanded, animated: true) }
}
delegate?.menuButton(self, isExpandedDidUpdate: isExpanded)
}
}
}
Related Topics
Remove Uisegmentedcontrol Separators Completely. (Iphone)
Why My App Is Not Shown in Icloud Drive Folder
Complete List of iOS App Permissions
Adding Click Event on Infowindow/Marker in Google Maps Sdk for Native iOS/Objective C
How to Embed a Uitableview in a Uiscrollview
Sudzc Arc Version - Objc_Msgsend Call Causes Exc_Bad_Access Using 64-Bit Architecture
Printing the View in iOS with Swift
Detect When a Webview Video Becomes Fullscreen on iOS8
iOS Get Heart Rate from Apple Watch in Near Real Time
Removing from Array During Enumeration in Swift
Cross Directional Uiscrollviews - How to Modify the Scrolling Behaviour