let frame = CGRect(x: 0, y: 0, width: 100, height: 100)
let textField = UITextField(frame: frame)
CGRect *frame = CGRectMake(0, 0, 100, 100);
UITextField *textField = [[UITextField alloc] initWithFrame:frame];
You can also add a UITextField
to a storyboard by dragging it from Object Library.
Add an accessory view above the keyboard. This is commonly used for adding next/previous buttons, or additional buttons like Done/Submit (especially for the number/phone/decimal pad keyboard types which don't have a built-in return key).
let textField = UITextField() // initialized however
let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 0)
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: Selector("done"))
let items = [flexibleSpace, doneButton] // pushes done button to right side
toolbar.setItems(items, animated: false) // or toolbar.items = ...
toolbar.sizeToFit()
textField.inputAccessoryView = toolbar
UITextField *textField = [[UITextField alloc] init];
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 0)];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(done)];
NSArray *items = @[
flexibleSpace,
doneButton
];
[toolbar setItems:items];
[toolbar sizeToFit];
textField.inputAccessoryView = toolbar;
textField.autocapitalizationType = .None
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
All options:
.None
\ UITextAutocapitalizationTypeNone
: Don't autocapitalize anything.Words
\ UITextAutocapitalizationTypeWords
: Autocapitalize every word.Sentences
\ UITextAutocapitalizationTypeSentences
: Autocapitalize the first word in a sentence.AllCharacters
\ UITextAutocapitalizationTypeAllCharacters
: Autocapitalize every letter (i.e. caps lock)Ctrl + Drag from the UItextfield in MainStoryboard to the ViewController Class and create a UITextField Outlet
After that select the UItextField again and Ctrl+drag in ViewController class but this time select Action connection and on storage select Did End On Exit then click connect.
in the action you just created type the name of your UItextField .resignFirstResponder()
@IBAction func textFieldResign(sender: AnyObject) {
yourTextFieldName.resignFirstResponder()
}
This will take care of hiding the keyboard when pressing the return key on keyboard.
Another example of hiding the keyboard when return key is pressed:
we add UITextFieldDelegate
protocol next to UIViewController
in the vieDidLoad function
we add self.yourTextFieldName.delegate = self
And Finally we add this
func textFieldShouldReturn(textField: UITextField) -> Bool {
yourTextFieldName.resignFirstResponder()
return true
}
The final code is this:
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var textField: UITextField!
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?){
view.endEditing(true)
super.touchesBegan(touches, withEvent: event)
}
override func viewDidLoad() {
super.viewDidLoad()
self.textField.delegate = self
}
}
[textField resignFirstResponder];
textField.textAlignment = .Center
[textField setTextAlignment: NSTextAlignmentCenter];
In the example, we have set the NSTextAlignment
to center. You can also set to .Left
, .Right
, .Justified
and .Natural
.
.Natural
is the default alignment for the current localization. That means for left-to-right languages (eg. English), the alignment is .Left
; for right-to-left languages, it is .Right
.
To change the appearance of the keyboard, the following types can be set individually on every UITextFields
property: keyboardType
typedef NS_ENUM(NSInteger, UIKeyboardType) {
UIKeyboardTypeDefault, // Default type for the current input method.
UIKeyboardTypeASCIICapable, // Displays a keyboard which can enter ASCII characters, non-ASCII keyboards remain active
UIKeyboardTypeNumbersAndPunctuation, // Numbers and assorted punctuation.
UIKeyboardTypeURL, // A type optimized for URL entry (shows . / .com prominently).
UIKeyboardTypeNumberPad, // A number pad (0-9). Suitable for PIN entry.
UIKeyboardTypePhonePad, // A phone pad (1-9, *, 0, #, with letters under the numbers).
UIKeyboardTypeNamePhonePad, // A type optimized for entering a person's name or phone number.
UIKeyboardTypeEmailAddress, // A type optimized for multiple email address entry (shows space @ . prominently).
UIKeyboardTypeDecimalPad NS_ENUM_AVAILABLE_IOS(4_1), // A number pad with a decimal point.
UIKeyboardTypeTwitter NS_ENUM_AVAILABLE_IOS(5_0), // A type optimized for twitter text entry (easy access to @ #)
UIKeyboardTypeWebSearch NS_ENUM_AVAILABLE_IOS(7_0), // A default keyboard type with URL-oriented addition (shows space . prominently).
UIKeyboardTypeAlphabet = UIKeyboardTypeASCIICapable, // Deprecated
};
Observe the notifications UIKeyboardWillShowNotification
and UIKeyboardWillHideNotification
, update the scrollView
content insets according to keyboard height, then scroll to the focused control.
- (void)viewDidLoad
{
[super viewDidLoad];
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:self.view.window];
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:self.view.window];
}
// Called when UIKeyboardWillShowNotification is sent
- (void)keyboardWillShow:(NSNotification*)notification
{
// if we have no view or are not visible in any window, we don't care
if (!self.isViewLoaded || !self.view.window) {
return;
}
NSDictionary *userInfo = [notification userInfo];
CGRect keyboardFrameInWindow;
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindow];
// the keyboard frame is specified in window-level coordinates. this calculates the frame as if it were a subview of our view, making it a sibling of the scroll view
CGRect keyboardFrameInView = [self.view convertRect:keyboardFrameInWindow fromView:nil];
CGRect scrollViewKeyboardIntersection = CGRectIntersection(_scrollView.frame, keyboardFrameInView);
UIEdgeInsets newContentInsets = UIEdgeInsetsMake(0, 0, scrollViewKeyboardIntersection.size.height, 0);
// this is an old animation method, but the only one that retains compaitiblity between parameters (duration, curve) and the values contained in the userInfo-Dictionary.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
_scrollView.contentInset = newContentInsets;
_scrollView.scrollIndicatorInsets = newContentInsets;
/*
* Depending on visual layout, _focusedControl should either be the input field (UITextField,..) or another element
* that should be visible, e.g. a purchase button below an amount text field
* it makes sense to set _focusedControl in delegates like -textFieldShouldBeginEditing: if you have multiple input fields
*/
if (_focusedControl) {
CGRect controlFrameInScrollView = [_scrollView convertRect:_focusedControl.bounds fromView:_focusedControl]; // if the control is a deep in the hierarchy below the scroll view, this will calculate the frame as if it were a direct subview
controlFrameInScrollView = CGRectInset(controlFrameInScrollView, 0, -10); // replace 10 with any nice visual offset between control and keyboard or control and top of the scroll view.
CGFloat controlVisualOffsetToTopOfScrollview = controlFrameInScrollView.origin.y - _scrollView.contentOffset.y;
CGFloat controlVisualBottom = controlVisualOffsetToTopOfScrollview + controlFrameInScrollView.size.height;
// this is the visible part of the scroll view that is not hidden by the keyboard
CGFloat scrollViewVisibleHeight = _scrollView.frame.size.height - scrollViewKeyboardIntersection.size.height;
if (controlVisualBottom > scrollViewVisibleHeight) { // check if the keyboard will hide the control in question
// scroll up until the control is in place
CGPoint newContentOffset = _scrollView.contentOffset;
newContentOffset.y += (controlVisualBottom - scrollViewVisibleHeight);
// make sure we don't set an impossible offset caused by the "nice visual offset"
// if a control is at the bottom of the scroll view, it will end up just above the keyboard to eliminate scrolling inconsistencies
newContentOffset.y = MIN(newContentOffset.y, _scrollView.contentSize.height - scrollViewVisibleHeight);
[_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
} else if (controlFrameInScrollView.origin.y < _scrollView.contentOffset.y) {
// if the control is not fully visible, make it so (useful if the user taps on a partially visible input field
CGPoint newContentOffset = _scrollView.contentOffset;
newContentOffset.y = controlFrameInScrollView.origin.y;
[_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
}
}
[UIView commitAnimations];
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillHide:(NSNotification*)notification
{
// if we have no view or are not visible in any window, we don't care
if (!self.isViewLoaded || !self.view.window) {
return;
}
NSDictionary *userInfo = notification.userInfo;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
// undo all that keyboardWillShow-magic
// the scroll view will adjust its contentOffset apropriately
_scrollView.contentInset = UIEdgeInsetsZero;
_scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;
[UIView commitAnimations];
}
Get Focus
textField.becomeFirstResponder()
[textField becomeFirstResponder];
Resign
textField.resignFirstResponder()
[textField resignFirstResponder];
In some cases, you want to show your users a UIPickerView
with predefined contents for a UITextField
instead of a keyboard.
Create a custom UIPickerView
At first, you need a custom wrapper-class for UIPickerView
conforming to the protocols UIPickerViewDataSource
and UIPickerViewDelegate
.
class MyPickerView: UIPickerView, UIPickerViewDataSource, UIPickerViewDelegate
You need to implement the following methods for the DataSource and Delegate:
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if data != nil {
return data!.count
} else {
return 0
}
}
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if data != nil {
return data![row]
} else {
return ""
}
}
To handle the data, MyPickerView
needs the properties data
, selectedValue
and textFieldBeingEdited
:
/**
The data for the `UIPickerViewDelegate`
Always needs to be an array of `String`! The `UIPickerView` can ONLY display Strings
*/
public var data: [String]? {
didSet {
super.delegate = self
super.dataSource = self
self.reloadAllComponents()
}
}
/**
Stores the UITextField that is being edited at the moment
*/
public var textFieldBeingEdited: UITextField?
/**
Get the selected Value of the picker
*/
public var selectedValue: String {
get {
if data != nil {
return data![selectedRow(inComponent: 0)]
} else {
return ""
}
}
}
Prepare your ViewController
The ViewController
that contains your textField, needs to have a property for your custom UIPickerView
. (Assuming, that you already have another property or @IBOutlet
containing your textField)
/**
The picker view to present as keyboard
*/
var picker: MyPickerView?
In your viewDidLoad()
, you need to initialize picker
and configure it a bit:
picker = MyPickerView()
picker?.autoresizingMask = [.flexibleHeight, .flexibleWidth]
picker?.backgroundColor = UIColor.white()
picker?.data = ["One", "Two", "Three", "Four", "Five"] //The data shown in the picker
Now, you can add the MyPicker
as inputView
of your UITextField
:
textField.inputView = picker
Dismissing the picker-keyboard
Now, you have replaced the keyboard by an UIPickerView
, but there is no possibility to dismiss it. This can be done with a custom .inputAccessoryView
:
Add the property pickerAccessory
to your ViewController
.
/**
A toolbar to add to the keyboard when the `picker` is presented.
*/
var pickerAccessory: UIToolbar?
In viewDidLoad()
, you need to create an UIToolbar
for the inputAccessoryView
:
pickerAccessory = UIToolbar()
pickerAccessory?.autoresizingMask = .flexibleHeight
//this customization is optional
pickerAccessory?.barStyle = .default
pickerAccessory?.barTintColor = UIColor.red()
pickerAccessory?.backgroundColor = UIColor.red()
pickerAccessory?.isTranslucent = false
You should set the frame of your toolbar. To fit in the design of iOS, it's recommended to use a height of 44.0
:
var frame = pickerAccessory?.frame
frame?.size.height = 44.0
pickerAccessory?.frame = frame!
For a good user experience, you should add two buttons ("Done" and "Cancel"), but it would also work with only one that dismisses the keyboard.
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(ViewController.cancelBtnClicked(_:)))
cancelButton.tintColor = UIColor.white()
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) //a flexible space between the two buttons
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(ViewController.doneBtnClicked(_:)))
doneButton.tintColor = UIColor.white()
//Add the items to the toolbar
pickerAccessory?.items = [cancelButton, flexSpace, doneButton]
Now you can add the toolbar as inputAccessoryView
textField.inputAccessoryView = pickerAccessory
Before you can build your project, you need to implement the methods, the buttons are calling:
/**
Called when the cancel button of the `pickerAccessory` was clicked. Dismsses the picker
*/
func cancelBtnClicked(_ button: UIBarButtonItem?) {
textField?.resignFirstResponder()
}
/**
Called when the done button of the `pickerAccessory` was clicked. Dismisses the picker and puts the selected value into the textField
*/
func doneBtnClicked(_ button: UIBarButtonItem?) {
textField?.resignFirstResponder()
textField.text = picker?.selectedValue
}
Run your project, tap the textField
and you should see a picker like this instead of the keyboard:
Select a value programmatically (optional)
If you don't want to have the first row selected automatically, you can set the selected row as in UIPickerView
:
picker?.selectRow(3, inComponent: 0, animated: false) //Will select the row at index 3
Setup your view controller to manage editing of text for the text field.
class MyViewController: UITextFieldDelegate {
override viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
}
}
textFieldShouldReturn
is called every time the return button on the keyboard is pressed.
Swift:
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true;
}
Objective-C:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return true;
}
The very beginning of the text field text:
let startPosition: UITextPosition = textField.beginningOfDocument
The very end of the text field text:
let endPosition: UITextPosition = textField.endOfDocument
The currently selected range:
let selectedRange: UITextRange? = textField.selectedTextRange
if let selectedRange = textField.selectedTextRange {
let cursorPosition = textField.offsetFromPosition(textField.beginningOfDocument, toPosition: selectedRange.start)
print("\(cursorPosition)")
}
In order to set the position, all of these methods are actually setting a range with the same start and end values.
To the beginning
let newPosition = textField.beginningOfDocument
textField.selectedTextRange = textField.textRangeFromPosition(newPosition, toPosition: newPosition)
To the end
let newPosition = textField.endOfDocument
textField.selectedTextRange = textField.textRangeFromPosition(newPosition, toPosition: newPosition)
To one position to the left of the current cursor position
// only if there is a currently selected range
if let selectedRange = textField.selectedTextRange {
// and only if the new position is valid
if let newPosition = textField.positionFromPosition(selectedRange.start, inDirection: UITextLayoutDirection.Left, offset: 1) {
// set the new position
textField.selectedTextRange = textField.textRangeFromPosition(newPosition, toPosition: newPosition)
}
}
To an arbitrary position
Start at the beginning and move 5 characters to the right.
let arbitraryValue: Int = 5
if let newPosition = textField.positionFromPosition(textField.beginningOfDocument, inDirection: UITextLayoutDirection.Right, offset: arbitraryValue) {
textField.selectedTextRange = textField.textRangeFromPosition(newPosition, toPosition: newPosition)
}
Select all text
textField.selectedTextRange = textField.textRangeFromPosition(textField.beginningOfDocument, toPosition: textField.endOfDocument)
Select a range of text
// Range: 3 to 7
let startPosition = textField.positionFromPosition(textField.beginningOfDocument, inDirection: UITextLayoutDirection.Right, offset: 3)
let endPosition = textField.positionFromPosition(textField.beginningOfDocument, inDirection: UITextLayoutDirection.Right, offset: 7)
if startPosition != nil && endPosition != nil {
textField.selectedTextRange = textField.textRangeFromPosition(startPosition!, toPosition: endPosition!)
}
Insert text at the current cursor position
textField.insertText("Hello")
This example originally comes from this Stack Overflow answer.
This answer uses a text field, but the same concepts apply to UITextView
.
Use textField.becomeFirstResponder()
to give focus to the text field and make the keyboard appear.
See this answer for how to get the text at some range.
selectedTextRange
here rather than just selectedRange
)To hide the blinking caret, you need to override caretRectForPosition of a UITextField and return CGRectZero.
public override func caretRectForPosition(position: UITextPosition) -> CGRect {
return CGRectZero
}
override func caretRect(for position: UITextPosition) -> CGRect {
return CGRect.zero
}
- (CGRect) caretRectForPosition:(UITextPosition*) position{
return CGRectZero;
}
We can change the style of the placeholder by setting attributedPlaceholder
(a NSAttributedString
).
var placeholderAttributes = [String: AnyObject]()
placeholderAttributes[NSForegroundColorAttributeName] = color
placeholderAttributes[NSFontAttributeName] = font
if let placeholder = textField.placeholder {
let newAttributedPlaceholder = NSAttributedString(string: placeholder, attributes: placeholderAttributes)
textField.attributedPlaceholder = newAttributedPlaceholder
}
In this example we change only the color
and font
. You could change other properties such as underline or strikethrough style. Refer to NSAttributedString
for the properties that can be changed.