Text inset for UITextField?
Overriding -textRectForBounds:
will only change the inset of the placeholder text. To change the inset of the editable text, you need to also override -editingRectForBounds:
// placeholder position
- (CGRect)textRectForBounds:(CGRect)bounds {
return CGRectInset(bounds, 10, 10);
}
// text position
- (CGRect)editingRectForBounds:(CGRect)bounds {
return CGRectInset(bounds, 10, 10);
}
Create space at the beginning of a UITextField
This is what I am using right now:
Swift 4.2
class TextField: UITextField {
let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
override open func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
override open func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
override open func editingRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
}
Swift 4
class TextField: UITextField {
let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
override open func textRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override open func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override open func editingRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
}
Swift 3:
class TextField: UITextField {
let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
override func textRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
}
I never set a other padding but you can tweak. This class doesn't take care of the rightView and leftView on the textfield. If you want that to be handle correctly you can use something like (example in objc and I only needed the rightView:
- (CGRect)textRectForBounds:(CGRect)bounds {
CGRect paddedRect = UIEdgeInsetsInsetRect(bounds, self.insets);
if (self.rightViewMode == UITextFieldViewModeAlways || self.rightViewMode == UITextFieldViewModeUnlessEditing) {
return [self adjustRectWithWidthRightView:paddedRect];
}
return paddedRect;
}
- (CGRect)placeholderRectForBounds:(CGRect)bounds {
CGRect paddedRect = UIEdgeInsetsInsetRect(bounds, self.insets);
if (self.rightViewMode == UITextFieldViewModeAlways || self.rightViewMode == UITextFieldViewModeUnlessEditing) {
return [self adjustRectWithWidthRightView:paddedRect];
}
return paddedRect;
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
CGRect paddedRect = UIEdgeInsetsInsetRect(bounds, self.insets);
if (self.rightViewMode == UITextFieldViewModeAlways || self.rightViewMode == UITextFieldViewModeWhileEditing) {
return [self adjustRectWithWidthRightView:paddedRect];
}
return paddedRect;
}
- (CGRect)adjustRectWithWidthRightView:(CGRect)bounds {
CGRect paddedRect = bounds;
paddedRect.size.width -= CGRectGetWidth(self.rightView.frame);
return paddedRect;
}
Set padding for UITextField with UITextBorderStyleNone
I found a neat little hack to set the left padding for this exact situation.
Basically, you set the leftView property of the UITextField
to be an empty view of the size of the padding you want:
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)];
textField.leftView = paddingView;
textField.leftViewMode = UITextFieldViewModeAlways;
Worked like a charm for me!
In Swift 3/ Swift 4, it can be done by doing that
let paddingView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 20))
textField.leftView = paddingView
textField.leftViewMode = .always
Change the text layout in a UITextField
You can sublcass to a custom TextField:
import UIKit
class CustomTextField: UITextField {
var inset:CGFloat = 12 // You can set the inset you want
override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.insetBy(dx: inset, dy: 0)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return bounds.insetBy(dx: inset, dy: 0)
}
}
The result, you can see the inset of the CustomTextField:
Edit
Adding top padding to UITextField
Use a customTextField class
class CustomTextField: UITextField {
let padding = UIEdgeInsets(top: 15, left: 0, bottom: 0, right: 0);
override func textRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
}
Swift 4 version, as per Micah's answer below:
class CustomTextField: UITextField {
let padding = UIEdgeInsets(top: 15, left: 0, bottom: 0, right: 0);
override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
}
Position text in a textfield
You cannot set position of text implicitly in UITextField without subclassing it.
You can use UITextView instead, and should use the same approach with it:
UITextView *textView;
UIEdgeInsets insets = UIEdgeInsetsMake(top, left, bottom, right);
[textView setContentInset:insets];
You can use this approach also with subclassing the UITextField.
Related Topics
Uiscrollview Scrollable Content Size Ambiguity
Programmatically Set the Initial View Controller Using Storyboards
Having a Uitextfield in a Uitableviewcell
Importing Commoncrypto in a Swift Framework
Iphone: Detecting User Inactivity/Idle Time Since Last Screen Touch
Class Does Not Implement Its Superclass'S Required Members
How to Count Occurrences of an Element in a Swift Array
Nsdictionary With Ordered Keys
Swift Png Image Being Saved With Incorrect Orientation
Change User Agent in Uiwebview
Iphone 6 Plus Resolution Confusion: Xcode or Apple'S Website? For Development
How to Trigger a Block After a Delay, Like -Performselector:Withobject:Afterdelay:
Swift - Json Error: the Data Couldn'T Be Read Because It Isn'T in the Correct Format
Swift Parse Json - the Data Couldn'T Be Read Because It Isn'T in the Correct Format
Assertion Failure in Dequeuereusablecellwithidentifier:Forindexpath: