Swift animations appear to be working in reverse - animation

I'm very new to iOS/xcode development, I'm trying to do something very basic as part of a tutorial exercise which is to fade a UILabel in once a user has completed a game.
So I'm hiding the label when the view loads:
override func viewDidLayoutSubviews() {
winMessageLabel.alpha = 0
}
And then on completion of the game I'm trying to fade it back in:
UIView.animateWithDuration(1, animations: { () -> Void in
self.winMessageLabel.alpha = 1
self.view.layoutIfNeeded()
})
But rather than fade in it appears with alpha 1 and then fades out. I get the same behaviour if I try to animate the x/y coordinates whereby it jumps to where I want it to go and then animates back to its original position

I've just worked it out - the layout is invalid so if I call layoutIfNeeded() prior to my animation it sorts everything out and then the label animates as expected:
self.view.layoutIfNeeded()
UIView.animateWithDuration(1, animations: { () -> Void in
self.winMessageLabel.alpha = 1
self.view.layoutIfNeeded()
})

Related

Adding SKNodes into a ScrollView?

On Android, I've previously used CCScrollView (part of Cocos2D-X) to add nodes to a scrollable container, with all the extras like the elastic bounce, scrollbars, swipe gestures, etc.
But I can't work out how to do this in Xcode. I know there's UIScrollView, but I'm writing for macOS. And there's SKCameraNode, but this seems to target the whole scene, rather than just part of the scene, I think.
I'd like to create a horizontal scrollable container for interactive sprite nodes. I know I could simply make the node move in relation to the mouse's x value, but that's not as pleasing as a simple scrollview.
I guess I could place a second scene within the scrollview, but that seems overkill and a performance hit. There's also third party solutions like SwiftySKScrollView but I'd like to avoid relying on such dependencies.
override func mouseDown(with event: NSEvent) {
scroller.removeAllActions()
scrollerPosX = scroller.position.x - event.location(in: self).x
}
override func mouseDragged(with event: NSEvent) {
mouseMomentum = event.deltaX
for node in nodes(at: event.location(in: self)) {
if node.isMember(of: Scroller.self) {
scroller.position.x = event.location(in: self).x + scrollerPosX
}
}
}
// This needs work to improve the ease out momentum, and a boundary bounce needs adding
override func mouseUp(with event: NSEvent) {
let moveby = SKAction.moveBy(x: mouseMomentum*10, y: 0, duration: 0.3)
moveby.timingMode = .easeOut
scroller.run(moveby)
}

Start and stop UISlider animation in Swift?

The question is simple - how to start and stop animation for UISlider programmatically?
func playSliderAnimation() {
view.slider.value = 0
UIView.animate(withDuration: duration) {
self.view.slider.setValue(1, animated: true)
}
}
func stopSliderAnimation() {
view.slider.value = 0
}
tried a lot of combinations for stopSliderAnimation - animating, without of animation, small animation duration, dispath into main queue - nothing works. The circle jumps left somewhere outside the bounds

Trying to animate a NSLayoutConstraint with Swift 3

I'm trying to animate a constraint but it seems to be effecting the entire view. Here is the code that I am using to animate the constraint.
#IBOutlet weak var personHeight: NSLayoutConstraint!
func animateBackgroundHeight() {
print("animate")
UIView.animate(withDuration: 5.0, animations: {
self.personHeight.constant = 19 // personHeight is the IBOutlet to the constraint
self.view.layoutIfNeeded()
})
}
Everything in the view moves when the animation is going on but I'm not sure why. What I want to animate is the height of the view, but not effect the TextField or the button. Think of the GreyView as a background element of the TextField.
Here is a image to show you which constraint I am trying to animate (green one)
Pink box represents the parent view.
Grey Box is the view that I am trying to animate the height of.
The TextField and button are above the Grey Box object.
You may animate the wrong view after all
so to be clear about your question
if you have x view that nested in another view
and want to animate only x view
then you should
make
self.x.layoutIfNeeded()
instead of
self.view.layoutIfNeeded()

fade in an bounce animation subview

I have an subview that fades into the view. this goes perfectly with this code:
UIView.animateWithDuration(0.9, animations: {
self.popUpView.backgroundColor = UIColor.blackColor()
})
But how can i make a sort of bounce? That the popupview fades in very hard and bounces a little bit back.
From UIView, you could use:
class func animateWithDuration(_ duration: NSTimeInterval,
delay delay: NSTimeInterval,
usingSpringWithDamping dampingRatio: CGFloat,
initialSpringVelocity velocity: CGFloat,
options options: UIViewAnimationOptions,
animations animations: () -> Void,
completion completion: ((Bool) -> Void)?)
To change the bounciness you'll want to change the dampingRatio; zero being the most bouncy and one being the least bouncy. From the UIView documentation:
Damping Ratio: The damping ratio for the spring animation as it approaches its quiescent state.
To smoothly decelerate the animation without oscillation, use a value
of 1. Employ a damping ratio closer to zero to increase oscillation.

Trying to move UIView off screen and use autolayout

I have a UIView that I would like to animate off the screen and then bring another view into the screen. I'm using auto layout and I have a IBOutlet set up for the left and right NSLayoutConstraint. Its seem that with out a width set for the UIView that the view actually doesn't animate off the screen.
I'm trying to use this code to pus the UIView off:
self.gameViewConstraintLeft.constant = -400
UIView.animateWithDuration(1, animations: { () in
self.view.layoutIfNeeded()
})
self.gameViewConstriantRight.constant = -400
UIView.animateWithDuration(1, animations: { () in
self.view.layoutIfNeeded()
})
I have constraints set up on the top(0), left(0) and right(0). Maybe this is my issue that I'm pinning the view to the edge of the screen, but I want this to work on multiple screen sizes, so I'm just not sure the best method of achieving my goal.
You are going to have problems moving the views if they're pinned on multiple sides horizontally or vertically.
I would suggest the following:
Set up width, height, centerX, and centerY constraints for your two views. The width and height can be set to "Equal Widths" and "Equal Heights" with the superview to allow it to work with multiple screen sizes.
Add an IBOutlets to the centerX constraint. Animate by modifying the constant property of this constraint:
self.gameView1ConstraintCenterX.constant = -400
UIView.animateWithDuration(1) {
self.view.layoutIfNeeded()
}
self.gameView2ConstriantCenterX.constant = 0
UIView.animateWithDuration(1) {
self.view.layoutIfNeeded()
}

Resources