6

I'm facing a problem : I have a very simple custom UIView which groups one UITextField and one UILabel.

The UILabel is on the UITextField, and I want that the UILabel go up to 40px when user begins to edit the UITextField.

I'm using constraints to set the textfield's frame and the label's frame.

So I just set the delegate in my custom view with UITextFieldDelegate protocol, and implement the delegate method : textFieldDidBeginEditing, as bellow :

I'm just animating the constraint (center Y) of my label in the delegate method.

func textFieldDidBeginEditing(textField: UITextField) {
    self.centerVerticallyLabelConstraint.constant = -40
    UIView.animateWithDuration(0.5) {
        self.textFieldLabel.layoutIfNeeded()
    }
}

What happens is that the UILabel goes up correctly, but it goes up instantly. It ignores the duration of 0.5 in my animation. I don't know why :

Show problem image

I'm not animating something else at the same time, I only have this animation. I haven't disable animations for UIView. The delegate is set to my UITextfield.

Any idea?

KSR
  • 1,699
  • 15
  • 22
AnthonyR
  • 3,485
  • 1
  • 18
  • 41

4 Answers4

11

Try calling layoutIfNeeded on your view instead of textview.

UIView.animate(withDuration: 0.5) {
    self.view.layoutIfNeeded()
}

Hope this helps.

Karen Hovhannisyan
  • 1,140
  • 2
  • 21
  • 31
nishith Singh
  • 2,968
  • 1
  • 15
  • 25
  • Thank you... I'm angry to haven't see this before ! – AnthonyR Sep 13 '16 at 12:03
  • I have been struggling with this for a day. In my case I was animating height constraint of a view, and I was animating it from the view itself. I didn't think at all I had to call the -layoutIfNeeded on the superview. Thank you. – Matteo Gobbi Dec 11 '19 at 00:30
0

Try Below code to execute:

func textFieldDidBeginEditing(textField: UITextField) {
    UIView.animate(withDuration: 0.5) {
        self.textFieldLabel.frame.origin.y -= 40
    }
}
Karen Hovhannisyan
  • 1,140
  • 2
  • 21
  • 31
Lawrence413
  • 1,976
  • 1
  • 14
  • 28
  • 1
    This will break autolayout constraints, which may be undesired. Animating constraints is a valid thing to do. – Losiowaty Sep 13 '16 at 12:08
0

need to call self.view.layoutIfNeeded() not self.textFieldLabel.layoutIfNeeded() Thanks

Jagveer Singh
  • 2,258
  • 19
  • 34
0

For me, the issue seems to be because I was already on the main thread & I called the animation block inside a GCD main.async call.

ie I had

DispatchQueue.main.async { 

<# update the constraint s#>

self.animatedViewsParent.setNeedsLayout() 
animatedView.setNeedsLayout()

UIView.animate(withDuration: 2.0) {
    self.animatedViewsParent.layoutIfNeeded()
  }
}

The view animates moves but does not animate gradually over 2.0 seconds. Removing the outer DispatchQueue.main.async {} solves the problem.

TMin
  • 2,280
  • 1
  • 25
  • 34