I am trying to move UITextFields when the Keyboard shows. Now I've seen videos and read articles on how to do it. I haven't seen one that uses the textfield itself, rather they use the bottom constraint of the textfield. Here is a video of what my code does, below is my code.
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var nameTF: UITextField!
#IBOutlet weak var emailTF: UITextField!
var selectedTextField: UITextField?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
createKeyboardNotification()
}
func createKeyboardNotification() {
NotificationCenter.default.addObserver(self, selector: #selector(respondToKeyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(respondToKeyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
#objc func respondToKeyboardWillShow(notification: Notification) {
adjustHeightForTextFields(isKeyboardHidden: false, notification: notification, textField: selectedTextField)
}
#objc func respondToKeyboardWillHide(notification: Notification) {
adjustHeightForTextFields(isKeyboardHidden: true, notification: notification, textField: selectedTextField)
}
func adjustHeightForTextFields(isKeyboardHidden: Bool, notification: Notification, textField: UITextField?) {
guard let userInfo = notification.userInfo else { return }
let keyboardFrameRect = userInfo[UIKeyboardFrameEndUserInfoKey] as! CGRect
if let textField = textField {
let textFieldYPosition = textField.frame.origin.y
if view.frame.maxY - textFieldYPosition > keyboardFrameRect.height {
UIView.animate(withDuration: 0.25) {
textField.frame.origin.y = (self.view.frame.maxY - textField.frame.size.height - keyboardFrameRect.height - 8)
}
}
else {
UIView.animate(withDuration: 0.25) {
let difference = textFieldYPosition - keyboardFrameRect.height
textField.frame.origin.y = difference + 16 + self.view.safeAreaInsets.bottom - 8
}
}
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldDidBeginEditing(_ textField: UITextField) {
switch textField {
case nameTF:
print("NAME")
selectedTextField = nameTF
break
case emailTF:
print("EMAIL")
selectedTextField = emailTF
break
default:
break
}
}
}
If you have seen the video, I've come across some strange things. First when you tap on the textfield it works like its suppose to, but when you start typing the textfield just disappears. I didn't come across this when I was using the textfield bottom constraint. Now the second part is when the keyboard is already shown the textfield doesn't animate correctly, until you click it twice.
Now I am not using a scrollview, but would like to push the whole content or would I need to use a scrollview. If you take a look at this video, you can better understand what I mean by wanting to push the content.
Would really appreciate any help provided, Thanks. :)
You need to move the view up only when the textField on the bottom becomes active.
//Create a global variable to use as our keyboardHeight
var keyboardHeight: CGFloat = 0.0
override func viewDidLoad() {
super.viewDidLoad()
//Set the delegate only for the emailTF
emailTF.delegate = self
//Set up an observer. This will help us calculate keyboard height dynamically, depending on the iPhone the app runs on.
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
}
#objc private func keyboardWillShow(notification: NSNotification) {
if let keyboardRectValue = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
keyboardHeight = keyboardRectValue.height
}
}
Then move the view up and down when the textField becomes active/inactive.
func textFieldDidBeginEditing(_ textField: UITextField) {
print("MOVE VIEW UP")
if self.view.frame.origin.y == 0{
self.view.frame.origin.y -= keyboardHeight
}
}
func textFieldDidEndEditing(_ textField: UITextField) {
print("MOVE VIEW DOWN")
if self.view.frame.origin.y != 0{
self.view.frame.origin.y += keyboardHeight
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
print("MOVE VIEW DOWN")
if self.view.frame.origin.y != 0{
self.view.frame.origin.y += keyboardHeight
}
return true
}
This should definitely work. Good luck!
I agree that it's not clear always. We do this in our app and we used a scroll view. We embed the entire page in the scroll view. Then we move the bottom of the scroll view up. Scrollviews are easy to implement.
#objc func keyboardWillShow(notification: NSNotification) {
// Only deal with this if the window is active and visible.
if !self.isViewLoaded || self.view.window == nil {
return
}
if let userInfo = notification.userInfo {
let keyboardFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as! CGRect
scrollView.frame = CGRect(x: view.frame.origin.x,y: view.frame.origin.y,width: view.frame.width, height: view.frame.height - keyboardFrame.height - 64)
}
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)))
}
And when the keyboard disappears:
#objc func keyboardWillHide(notification: NSNotification) {
scrollView.frame = scrollViewOriginalFrame
}
Related
This has been asked a few times before: 1 2 3 4
These threads did not provide the solution I was looking for, and are getting a bit outdated with the release of Swift 5, so I've posted my solution below.
I recommend using IQKeyboardManagerSwift (or IQKeyboardManager written in ObjC) library that you can install with cocoapods, all tutorials included in link. For me it works better that custom solutions. Here are 2 versions of the library, ObjC and Swift :
Swift verion: https://cocoapods.org/pods/IQKeyboardManagerSwift
ObjC version: https://cocoapods.org/pods/IQKeyboardManager
This is my current solution:
import UIKit
// For UITextViews, exact same code, but using UITextViewDelegate
class viewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField: UITextField!
// Keeps track of our editing frame
// Kept it as a CGRect so that it can work with both UITextFields and UITextViews
var editingFrame: CGRect?
override func viewDidLoad() {
super.viewDidLoad()
// Set the delegate for the textField(s)
textField.delegate = self
// Add notification observers for keyboard
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillChangeFrame(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}
func textFieldDidBeginEditing(_ textField: UITextField) {
editingFrame = textField.frame
// This is the bit that is important, especially if you have
// your textfield inside another view (UIStackViews for example)
// The loop essentially goes through each successive superview the textfield has
// and redefines the centre in that superview's frame of reference
var currentView: UIView? = textField.superview
while currentView != nil {
editingFrame?.origin.x += currentView?.frame.origin.x ?? CGFloat(0.0)
editingFrame?.origin.y += currentView?.frame.origin.y ?? CGFloat(0.0)
currentView = currentView?.superview
}
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
editingFrame = nil
return true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
view.endEditing(true)
return true
}
#objc func keyboardWillChangeFrame(notification: Notification) {
if let editingFrame = editingFrame {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect) {
let offset = editingFrame.maxY - keyboardSize.minY
if offset > self.view.frame.origin.y {
self.view.frame.origin.y -= offset
} else {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y = 0
}
}
}
} else {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y = 0
}
}
}
#objc func endEditingTextFields() {
view.endEditing(true)
}
}
I am using scrolview for view with height 1000, initially i don't want my scrolView to scroll. if i tap on any textField then i want my scrolview to scroll and if i return keyboard then i don't want my scrollview to scroll.
Here i am able to textfield up when when keyboard appears but i am unable to return textfield to its orginal position when i return keyboard and when i return keyboard i dont want my view to scroll,
Please help me in the code.
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var scrolView: UIScrollView!
#IBOutlet weak var upTFLD: UITextField!
var activeTextField = UITextField()
#IBOutlet weak var downTFLD: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
upTFLD.delegate = self
downTFLD.delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardAppear(_:)), name: UIResponder.keyboardDidShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardDisappear(_:)), name: UIResponder.keyboardDidHideNotification, object: nil)
}
#objc func onKeyboardAppear(_ notification: NSNotification) {
let info = notification.userInfo!
let rect: CGRect = info[UIResponder.keyboardFrameBeginUserInfoKey] as! CGRect
let kbSize = rect.size
let insets = UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height+20, right: 0)
self.scrolView.contentInset = insets
self.scrolView.scrollIndicatorInsets = insets
var visibleRect: CGRect = self.scrolView.convert(self.scrolView.bounds, to: self.view)
visibleRect.size.height -= rect.size.height;
let inputRect: CGRect = self.activeTextField.convert(self.activeTextField.bounds, to: self.scrolView)
if (visibleRect.contains(inputRect)) {
self.scrolView.scrollRectToVisible(inputRect, animated: true)
}
}
#objc func onKeyboardDisappear(_ notification: NSNotification) {
self.scrolView.contentInset = UIEdgeInsets.zero
self.scrolView.scrollIndicatorInsets = UIEdgeInsets.zero
}
public func textFieldDidBeginEditing(_ textField: UITextField) {
activeTextField = textField
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
activeTextField.resignFirstResponder()
return true
}
}
initially i dont want scrolling, and if i return keyboard i need textfield come to its original position and no scrolling again.
Only keyboard appears then only i need scrolling. please help me in the code.
You just need to set the contentOffset of your ScrollView right after the keyboard is hidden.
Create a variable to store offsetBeforeShowKeyboard
var offsetBeforeShowKeyboard: CGFloat?
When view is initially loaded:
self.scrollView.isScrollEnabled = false
When select any TextField:
public func textFieldDidBeginEditing(_ textField: UITextField) {
self.scrollView.isScrollEnabled = true
if (self.offsetBeforeShowKeyboard == nil) {
self.offsetBeforeShowKeyboard = self.scrollView.contentOffset
}
}
When keyboard is hidden
#objc func onKeyboardDisappear(_ notification: NSNotification) {
self.scrollView.isScrollEnabled = false
if let offset = self.offsetBeforeShowKeyboard {
self.scrolView.setContentOffset(offset, animated: true)
}
self.offsetBeforeShowKeyboard = nil
}
In viewWillAppear
yourScrollview.isScrollEnabled = false
After Keyboard appears make it true
yourScrollview.isScrollEnabled = true
Alternatively you can use IQKeyboard manager to take care of textfields.Checkout: IQKeyboardManager
I'm populating a vertical UIScrollView with many UITextField fields dynamically on runtime. The problem I have is that the keyboard will hide the fields that are in the area where it will appear, this may include the field I'm editing.
I tried KeyboardManagement solution from the apple documentation and also tried with notifications on the textFieldDidBeginEditing and textFieldDidEndEditing but the problem in both cases is that the keyboardWillShow notification comes first sometimes, and in that case it doesn't let me know which field is the one being edited.
I have this code in a class that implements the UITextFieldDelegate protocol, each object of this class holds a reference to one of those fields and works as it's delegate
func textFieldDidBeginEditing(_ textField: UITextField) {
self.activeTextfield = self.valueTextField
}
func textFieldDidEndEditing(_ textField: UITextField) {
self.activeTextfield = nil
}
The activeTextfield variable is a weak reference to the variable in the UIViewController where all of this happens. In that view controller I have the following code
class MyClass: UIViewController {
var activeTextfield: CustomTextField! // This is the variable I was talking about on the previous paragraph
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
#objc func keyboardWillShow(_ notification: Notification) {
if self.view.frame.origin.y == 0 {
guard let userInfo = notification.userInfo else { return }
guard let keyboardSize = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
let keyboardFrame = keyboardSize.cgRectValue
let textFieldFrame = activeTextfield!.frame // activeTextfield sometimes is nil because this notification happens before the previous code block
if textFieldFrame.origin.y + textFieldFrame.size.height > keyboardFrame.origin.y {
self.view.frame.origin.y -= keyboardFrame.height
}
}
}
#objc func keyboardWillHide(_ notification: Notification) {
if self.view.frame.origin.y != 0 {
guard let userInfo = notification.userInfo else { return }
guard let keyboardSize = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
let keyboardFrame = keyboardSize.cgRectValue
self.view.frame.origin.y += keyboardFrame.height
}
}
}
Is there any way I can force the UITextField delegate methods to be called before the keyboard notification?
Is this the correct way to handle this kind of situation?
If not, how should I handle it?
Thanks
As stated in your question:
the problem in both cases is that the keyboardWillShow notification
comes first sometimes, and in that case it doesn't let me know which
field is the one being edited
As per the sequence of events described in apple's documentation, textFieldShouldBeginEditing is the first delegate method called.
So, you can
implement textFieldShouldBeginEditing in the delegate to set your active text field, instead of textFieldDidBeginEditing (make sure you return true from textFieldShouldBeginEditing to allow editing)
use keyboardDidShowNotification instead of keyboardWillShowNotification.
This will ensure you have your UITextField marked before getting the keyboard frame / details.
You can do so fairly simply by doing the following. First add notification observers in your view will appear.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Keyboard notification
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
Then in your selector function you can have something like this
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
let currentTextField = view.getSelectedTextField() {
let keyboardHeight = keyboardSize.height
let textFieldFrame = currentTextField.superview?.convert(currentTextField.frame, to: nil)
}
}
}
And your getSelectedTextField() extension looks like this
// Inside UIView Extension
// Get currently active textfield
func getSelectedTextField() -> UITextField? {
let totalTextFields = getTextFieldsInView(view: self)
for textField in totalTextFields{
if textField.isFirstResponder{
return textField
}
}
return nil
}
func getTextFieldsInView(view: UIView) -> [UITextField] {
var totalTextFields = [UITextField]()
for subview in view.subviews as [UIView] {
if let textField = subview as? UITextField {
totalTextFields += [textField]
} else {
totalTextFields += getTextFieldsInView(view: subview)
}
}
return totalTextFields
}
}
You need to define tag property to your textFields and check in
textFieldDidBeginEditing and textFieldDidEndEditing what UITextField was called.
I have created an extension of UIScrollView where when a user selects a textfield and the keyboard appears, the textfield will scroll up if it is in the way of the keyboard. I have it working for a UITextField but it doesn't seem to work with a UITextView. I have searched many posts on stackoverflow but can't seem to find anything to help. Here is the code for the extension:
extension UIScrollView {
func respondToKeyboard() {
self.registerForKeyboardNotifications()
}
func registerForKeyboardNotifications() {
// Register to be notified if the keyboard is changing size i.e. shown or hidden
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: #selector(keyboardWasShown(_:)),
name: UIKeyboardWillShowNotification,
object: nil
)
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: #selector(keyboardWillBeHidden(_:)),
name: UIKeyboardWillHideNotification,
object: nil
)
}
func keyboardWasShown(notification: NSNotification) {
if let info = notification.userInfo,
keyboardSize = info[UIKeyboardFrameBeginUserInfoKey]?.CGRectValue.size {
self.contentInset.bottom = keyboardSize.height + 15
self.scrollIndicatorInsets.bottom = keyboardSize.height
var frame = self.frame
frame.size.height -= keyboardSize.height
}
}
func keyboardWillBeHidden(notification: NSNotification) {
self.contentInset.bottom = 0
self.scrollIndicatorInsets.bottom = 0
}
In my view controller I would just set it like:
scrollView.respondToKeyboard()
Can someone point me in the right direction of how I can implement the UITextView as an extension to move up if the keyboard is in the way?
You can try using the UITextView delegate methods. Check out this link for more details. For swift, check the tutorial here.
for me this solution works fine for UITextView. Perhaps u can update this for Scrollview
// keyboard visible??
lazy var keyboardVisible = false
// Keyboard-Height
lazy var keyboardHeight: CGFloat = 0
func updateTextViewSizeForKeyboardHeight(keyboardHeight: CGFloat) {
textView.contentInset.bottom = keyboardHeight
self.keyboardHeight = keyboardHeight
}
func keyboardDidShow(notification: NSNotification) {
if let rectValue = notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue {
if keyboardVisible == false {
let keyboardSize = rectValue.CGRectValue().size
keyboardVisible = true
updateTextViewSizeForKeyboardHeight(keyboardSize.height)
}
}
}
func keyboardDidHide(notification: NSNotification) {
if keyboardVisible {
keyboardVisible = false
updateTextViewSizeForKeyboardHeight(0)
}
}
I have a MainView that adds a subview (signUpWindow) when a sign up button is pressed.
In my signUpWindow subview (SignUpWindowView.swift), I set up each field with a function, as an example:
func confirmPasswordText()
{
confirmPasswordTextField.frame=CGRectMake(50, 210, 410, 50)
confirmPasswordTextField.placeholder=("Confirm Password")
confirmPasswordTextField.textColor=textFieldFontColor
confirmPasswordTextField.secureTextEntry=true
confirmPasswordTextField.returnKeyType = .Next
confirmPasswordTextField.clearButtonMode = .WhileEditing
confirmPasswordTextField.tag=5
self.addSubview(confirmPasswordTextField)
}
I have the keyboard moving the signUpWindow up and down when it appears and disappears in the MainView.
SignUpWindowView implements the UITextFieldDelegate
My problem is that I am trying to configure the Next/Done button on the keyboard and am not sure which view (MainView or SignUpWindowView) to add the textFieldShouldReturn function. I have tried both, but can't even get a println to fire to test to see if the function is even being executed. Once I get the textFieldShouldReturn to fire, I am confident I can execute the necessary code to get the Next/Done buttons to do what I want, and will post the final solution to include the Next/Done function.
UPDATED to include an abbreviated version of SignUpWindowView.swift
import UIKit
class SignUpWindowView: UIView,UITextFieldDelegate {
let firstNameTextField:UITextField=UITextField()
let lastNameTextField:UITextField=UITextField()
override func drawRect(rect: CGRect){
func firstNameText(){
firstNameTextField.delegate=self
firstNameTextField.frame=CGRectMake(50, 25, 200, 50)
firstNameTextField.placeholder="First Name"
firstNameTextField.returnKeyType = .Next
self.addSubview(firstNameTextField)
}
func lastNameText(){
lastNameTextField.delegate=self
lastNameTextField.frame=CGRectMake(260, 25, 200, 50)
lastNameTextField.placeholder="Last Name"
lastNameTextField.returnKeyType = .Done
self.addSubview(lastNameTextField)
}
func textFieldShouldReturn(textField: UITextField!) -> Bool{
println("next button should work")
if (textField === firstNameTextField)
{
firstNameTextField.resignFirstResponder()
lastNameTextField.becomeFirstResponder()
}
return true
}
firstNameText()
lastNameText()
}
You need to implement UITextFieldDelegate in your class and set that object as the delegate for the UITextField. Then implement the method textFieldShouldReturn: like this:
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
if textField == someTextField { // Switch focus to other text field
otherTextField.becomeFirstResponder()
}
return true
}
In your example you are missing this line:
confirmPasswordTextField.delegate = self
If you have implemented the delegate of course.
I was attempting to test my textfields in the SignUpWindowView.swift, which is where all of the textFields are created. But, since I place SignUpWindowView into my MainViewController as a subview, all of my UITextField "handling" needed to be done in the MainView and NOT its subview.
So here is my entire code (at the moment) for my MainViewController, which handles moving my SignUpWindowView up/down when the keyboard is shown/hidden and then moves from one field to the next. When the user is in the last text field (whose keyboard Next button is now set to Done in the subview) the keyboard tucks away and the user can then submit the form with a signup button.
MainViewController:
import UIKit
#objc protocol ViewControllerDelegate
{
func keyboardWillShowWithSize(size:CGSize, andDuration duration:NSTimeInterval)
func keyboardWillHideWithSize(size:CGSize,andDuration duration:NSTimeInterval)
}
class ViewController: UIViewController,UITextFieldDelegate
{
var keyboardDelegate:ViewControllerDelegate?
let signUpWindow=SignUpWindowView()
let signUpWindowPosition:CGPoint=CGPointMake(505, 285)
override func viewDidLoad()
{
super.viewDidLoad()
// Keyboard Notifications
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
// set the textFieldDelegates
signUpWindow.firstNameTextField.delegate=self
signUpWindow.lastNameTextField.delegate=self
signUpWindow.userNameTextField.delegate=self
signUpWindow.passwordTextField.delegate=self
signUpWindow.confirmPasswordTextField.delegate=self
signUpWindow.emailTextField.delegate=self
}
func keyboardWillShow(notification: NSNotification)
{
var info:NSDictionary = notification.userInfo!
let keyboardFrame = info[UIKeyboardFrameEndUserInfoKey] as! NSValue
let keyboardSize = keyboardFrame.CGRectValue().size
var keyboardHeight:CGFloat = keyboardSize.height
let animationDurationValue = info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
var animationDuration : NSTimeInterval = animationDurationValue.doubleValue
self.keyboardDelegate?.keyboardWillShowWithSize(keyboardSize, andDuration: animationDuration)
// push up the signUpWindow
UIView.animateWithDuration(animationDuration, delay: 0.25, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
self.signUpWindow.frame = CGRectMake(self.signUpWindowPosition.x, (self.signUpWindowPosition.y - keyboardHeight+140), self.signUpWindow.bounds.width, self.signUpWindow.bounds.height)
}, completion: nil)
}
func keyboardWillHide(notification: NSNotification)
{
var info:NSDictionary = notification.userInfo!
let keyboardFrame = info[UIKeyboardFrameEndUserInfoKey] as! NSValue
let keyboardSize = keyboardFrame.CGRectValue().size
var keyboardHeight:CGFloat = keyboardSize.height
let animationDurationValue = info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
var animationDuration : NSTimeInterval = animationDurationValue.doubleValue
self.keyboardDelegate?.keyboardWillHideWithSize(keyboardSize, andDuration: animationDuration)
// pull signUpWindow back to its original position
UIView.animateWithDuration(animationDuration, delay: 0.25, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
self.signUpWindow.frame = CGRectMake(self.signUpWindowPosition.x, self.signUpWindowPosition.y, self.signUpWindow.bounds.width, self.signUpWindow.bounds.height)
}, completion: nil)
}
func textFieldShouldReturn(textField: UITextField) -> Bool
{
switch textField
{
case signUpWindow.firstNameTextField:
signUpWindow.lastNameTextField.becomeFirstResponder()
break
case signUpWindow.lastNameTextField:
signUpWindow.userNameTextField.becomeFirstResponder()
break
case signUpWindow.userNameTextField:
signUpWindow.passwordTextField.becomeFirstResponder()
break
case signUpWindow.passwordTextField:
signUpWindow.confirmPasswordTextField.becomeFirstResponder()
break
case signUpWindow.confirmPasswordTextField:
signUpWindow.emailTextField.becomeFirstResponder()
break
default:
textField.resignFirstResponder()
}
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
#IBAction func signup()
{
signUpWindow.frame=CGRectMake(signUpWindowPosition.x, signUpWindowPosition.y, 485,450)
signUpWindow.backgroundColor=UIColor.clearColor()
self.view.addSubview(signUpWindow)
}
}
Using tags makes it easier. Assign tags in ascending order to all the text fields you are using on your screen.
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let textTag = textField.tag+1
if let nextResponder = textField.superview?.viewWithTag(textTag) as UIResponder
{
//textField.resignFirstResponder()
nextResponder.becomeFirstResponder()
}
else {
// stop editing on pressing the done button on the last text field.
self.view.endEditing(true)
}
return true
}
You connect the DidEndOnExit(I wrote this from memory so maybe its not called this exactly but similar) UIControl event using an #IBAction and in that func you use textF.resignFirstResponder() or .becomeFirstResponder()
EDIT
UITextField is subclass of UIControl and to programatically add a new event you use the addTarget() method. Ex:
func a(sender: AnyObject) {}
textField.addTarget(self, action: "a:", forControlEvents: .EditingDidEndOnExit)
UIControl docs