问题
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()
}
回答1:
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.
回答2:
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)
}
}
回答3:
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
let nextResponder = textField.superview?.viewWithTag(textTag) as UIResponder!
if(nextResponder != nil)
{
//textField.resignFirstResponder()
nextResponder?.becomeFirstResponder()
}
else{
// stop editing on pressing the done button on the last text field.
self.view.endEditing(true)
}
return true
}
回答4:
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
来源:https://stackoverflow.com/questions/29925851/next-done-button-using-swift-with-textfieldshouldreturn