Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialBrandon Maldonado Alonso
10,050 PointsWhy my solution of moving my textfield doesn't work?
The problem is that I implemented the first animation to move when the keyboard appear, now i'm trying to do almost the same, just animate the textfield when the keyboard disappear but I don't know why it is not working.
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
// Creation of the textField and the animate-able constraints
let textField = UITextField()
private var textFieldXConstraint: NSLayoutConstraint?
private var textFieldYConstraint: NSLayoutConstraint?
let startButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.keyboardWillDissappear(_:)), name: UIKeyboardWillHideNotification, object: nil)
textField.delegate = self
startButton.enabled = false
startButton.alpha = 0.3
startButton.setTitle("Start Adventure", forState: UIControlState.Normal)
startButton.addTarget(self, action: #selector(ViewController.startButtonDidTouch), forControlEvents: UIControlEvents.TouchUpInside)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "startAdventure" {
if let pageController = segue.destinationViewController as? PageController, let text = textField.text {
pageController.page = Adventure.story(text)
}
}
}
// MARK: Helper methods
func keyboardWillShow(notification: NSNotification) {
if let userInfo = notification.userInfo, keyboardFrameValue = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue {
let keyboardFrame = keyboardFrameValue.CGRectValue()
UIView.animateWithDuration(0.8, animations: {
self.textFieldYConstraint?.constant -= keyboardFrame.size.height
self.view.layoutIfNeeded()
})
}
}
func keyboardWillDissappear(notification: NSNotification) {
UIView.animateWithDuration(0.8, animations: {
self.textFieldYConstraint?.constant += 100
print(self.textFieldYConstraint!)
self.view.layoutIfNeeded()
})
}
// This happen when you press the start adventure button
func startButtonDidTouch() {
performSegueWithIdentifier("startAdventure", sender: self)
}
// MARK: UI Creation
override func viewWillLayoutSubviews() {
view.addSubview(startButton)
startButton.translatesAutoresizingMaskIntoConstraints = false
startButton.tintColor = UIColor.whiteColor()
NSLayoutConstraint.activateConstraints([
startButton.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor),
startButton.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor, constant: -48.0)
])
view.addSubview(textField)
textField.translatesAutoresizingMaskIntoConstraints = false
textField.minimumFontSize = 24.0
textField.placeholder = "Write your name"
textField.borderStyle = .RoundedRect
textFieldXConstraint = NSLayoutConstraint(item: textField, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)
textFieldYConstraint = NSLayoutConstraint(item: textField, attribute: NSLayoutAttribute.BottomMargin, relatedBy: NSLayoutRelation.LessThanOrEqual, toItem: startButton, attribute: NSLayoutAttribute.TopMargin, multiplier: 1, constant: -24)
if textFieldXConstraint != nil && textFieldYConstraint != nil {
view.addConstraint(textFieldXConstraint!)
view.addConstraint(textFieldYConstraint!)
}
}
// MARK: TextField Helper Methods
// called when 'return' key pressed. return NO to ignore.
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
// called when users tap out of textfield
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
// Checks if there is a name to activate the button
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let lenght = (textField.text?.characters.count)! - (range.length) + (string.characters.count)
if lenght > 0 {
startButton.enabled = true
startButton.alpha = 1.0
} else {
startButton.enabled = false
startButton.alpha = 0.3
}
return true
}
// MARK: deinit
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
}
4 Answers
Andres Aguero
30,545 PointsAlmost there! Your function for the code constraints is too much. Your function for keyboardWillDissappear should be
func keyboardWillDissappear(notification: NSNotification) {
UIView.animateWithDuration(0.8) {
self.textFieldBottomConstraint.constant = 40.0
self.view.layoutIfNeeded()
}
}
The code resets the constraints.
Andres Aguero
30,545 PointsInteresting seems as if you added the button manually and not from main.storyboard am I correct? The reason why he added the button from the main.storyboard is so that we would be able to manipulate the constraint of the button by assigning it the constraint to an outlet. "@IBOutlet weak var textFieldBottomConstraint: NSLayoutConstraint!"
In your code you did not add an outlet. But your code in theory should work because if you were to "print(self.textFieldYConstraint!)" and compare it from when it was moved the button should have been reset. The button is just not updating its location itself. Not sure if there is some sort of special code for it.
Brandon Maldonado Alonso
10,050 PointsI tried to add everything programmatically, I figured out that if I move the code from viewWillLayoutSubview to viewDidLoad the code works how I want, I don't understand why and I'm not sure if this is a good practice, do you have any idea?
Andres Aguero
30,545 PointsHere is a good article on best practices of viewDidLoad method. http://blog.stablekernel.com/uiviewcontroller-best-practices-viewwillappear-or-viewdidload/
Brandon Maldonado Alonso
10,050 Pointsso where should I implement my auto layout code?
Andres Aguero
30,545 PointsIf it works in the viewDidLoad then leave it there
Brandon Maldonado Alonso
10,050 PointsBrandon Maldonado Alonso
10,050 PointsIt doesn't work, here is the zip file:https://drive.google.com/file/d/0B3D8byBTWoOVZWZZTC1HcXhjaEE/view?usp=sharing