Create space at the beginning of a UITextField
Solution 1
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;
}
Solution 2
This is a great case for an extension. By using an extension, there is no need to subclass UITextField and the new functionality will be made available to any UITextField in your app:
extension UITextField {
func setLeftPaddingPoints(_ amount:CGFloat){
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.frame.size.height))
self.leftView = paddingView
self.leftViewMode = .always
}
func setRightPaddingPoints(_ amount:CGFloat) {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.frame.size.height))
self.rightView = paddingView
self.rightViewMode = .always
}
}
When I need to set the padding of a text field anywhere in my application, I simply do the following:
textField.setLeftPaddingPoints(10)
textField.setRightPaddingPoints(10)
Using Swift extensions, the functionality is added to the UITextField directly without subclassing.
Hope this helps!
Solution 3
X, Y , Z are your desired values
textField.layer.sublayerTransform = CATransform3DMakeTranslation(x, y, z)
Solution 4
Such margin can be achieved by setting leftView
/ rightView
to UITextField
.
Updated For Swift 4
// Create a padding view for padding on left
textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 15, height: textField.frame.height))
textField.leftViewMode = .always
// Create a padding view for padding on right
textField.rightView = UIView(frame: CGRect(x: 0, y: 0, width: 15, height: textField.frame.height))
textField.rightViewMode = .always
I just added/placed an UIView
to left and right side of the textfield. So now the typing will start after the view.
Thanks
Hope this helped...
Solution 5
Swift 4, Xcode 9
I like Pheepster's answer, but how about we do it all from the extension, without requiring VC code or any subclassing:
import UIKit
@IBDesignable
extension UITextField {
@IBInspectable var paddingLeftCustom: CGFloat {
get {
return leftView!.frame.size.width
}
set {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
leftView = paddingView
leftViewMode = .always
}
}
@IBInspectable var paddingRightCustom: CGFloat {
get {
return rightView!.frame.size.width
}
set {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
rightView = paddingView
rightViewMode = .always
}
}
}
Related videos on Youtube
LinusGeffarth
I'm co-founder & CTO at Funeral Marketplace, a B2B2C online marketplace connecting every player in the funeral industry. I'm also head of software development at CONVELA and have my own little development studio for side projects: ögli{codes}. I've started out as project manager building a little app with my uncle; then began developing for iOS my own (for iPad using Obj-C at the time); made some iPhone and iPad apps (Swift). Eventually we founded the Funeral Marketplace, for which I led the iOS development (Swift) and managed the web (react.js) & backend (php, laravel) development. I then began developing for the frontend and backend as well, while also building my knowledge in server-side swift using the Vapor framework making me full-stack. #SOreadytohelp Stack Overflow to me, means endless possibilities. I feel like I can do anything using all the never-ending source of knowledge people share on SO. I am #SOreadytohelp because I want to give back exactly what I got and much more. I want to share my knowledge as much as possible to help people around the world progress and create beautiful things. I want to thank Stack Overflow for teaching me to code & helping me out every day. ♡
Updated on August 30, 2021Comments
-
LinusGeffarth almost 3 years
I want to leave a bit of space at the beginning of a UITextField, just like here: Add lefthand margin to UITextField
But I don't know how to do that with Swift.
-
Grady Player almost 10 yearswell, you can't subclass swift objects in Objective-C, but you can do it the other way around... So my guess you you just adjust the answer and combine it with: developer.apple.com/library/prerelease/ios/documentation/Swift/…
-
ipalibowhyte almost 10 yearsThis is probably not the best solution, but you could make a uiview *paddingView and do
UITextField.leftView = paddingView
. so give the padding view your desired width. -
Grady Player almost 10 yearsthe padding view would just be a vanilla UIView that has the width that you would like
-
J A S K I E R over 4 yearsFor Swift 5: textField.layoutMargins.left = 20
-
-
Haagenti over 9 yearsThis is almost perfect. You probably have a placeholder which has a like wise method: "placeholderRectForBounds" which you should also override and what you add as an x should be subtracted from the width otherwise you can't see you what type when the text goes beyond the length of the field
-
Haagenti over 9 yearsif left is 25 width should be minus 50 to have equal padding
-
Ash about 9 yearsWhy are you doubling the top and left insets when calculating width and height? Shouldn't need to do that. You should add the two relevant insets together and subtract the total from the original bounds. Or just subtract both in sequence.
-
Haagenti over 8 years@Mr.UB Check what platform the current device is and create different padding based on that. stackoverflow.com/questions/4567728/…. Probably with something like this
-
Mobile Dan about 8 yearsApple provides the equivalent of the
newBounds
method with theUIEdgeInsetsInsetRect
function. Instead ofreturn self.newBounds(bounds)
you could usereturn UIEdgeInsetsInsetRect(bounds, padding)
and remove thenewBounds
method. -
Avaan about 8 yearsif someone needed in "objective c" here is the code, UIView* paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 15, self. userNameTxtFldOutlet.frame.size.height)]; self. userNameTxtFldOutlet.leftView = paddingView; self. userNameTxtFldOutlet.leftViewMode = UITextFieldViewModeAlways;
-
justNate almost 8 yearsThis does not seem to work with textField.clearButtonMode = UITextFieldViewMode.Always – the clear button is moved to the right as well
-
Nermin Sehic over 7 yearsExcellent solution, very elegant. The only change I made was that I added them into one function so I get something like textField.setPaddingFor(left: 10, right: 10). Both params, are optional hence if you pass nil the padding will be 0.
-
Peter Kreinz over 7 yearsGreat! But If you set textField.clearButtonMode = .always, you have to set only the left padding. The right padding will move the clear button to the right.
-
xdev over 7 yearsDoes not work when Clear button needs to be shown...the clear button is moved as well.
-
Haagenti about 7 yearsThis anwer is short but not complete and might bug out later. @Adrian you have a great point, but this is not the way. The reason you've to do it with a subclass is for all the edge cases. This code will probably crash before the subclass solution. But you are right that you shouldn't write code that is not strictly needed and can be provide by using the given libraries, but you shouldn't abuse the standard libraries either
-
hasan over 6 yearsOne observation. It's more like a leading/trailing padding. But, the weird thing is that it responses to the textfield text alignment!! not the app language direction.
-
Tal over 6 yearsIt'd be safer to do
rightView?.frame.size.width ?? 0
-
Teodor Ciuraru over 6 yearsIt might. I, for myself, don't ever call the getter so it doesn't bother me.
-
Miki over 6 yearsThis does not work for UITextField inside a UISearchBar. :( I need the solution that works specifically in that case :(
-
Haagenti over 6 years@livtay This will not work when you use clearButtonMode or want to have an leftView, etc. This is a quick win though but just be aware the hole you're going in.
-
Teodor Ciuraru over 6 yearsGuys, I modified the methods' names from
paddingLeft
topaddingLeftCustom
and the other one too. If I haven't done this, a bug that followed me two weeks would've appeared when you were using Views that do have a UITextView (like UISearchBar). Just... don't set the default names. -
Sharkes Monken about 5 yearsShouldn't extension work better rather than introducing a shared class for such a minor task ?
-
Naresh about 5 years@ Sharkes Monken , I con't understood
-
Naresh about 5 years@ Sharkes Monken, can u please explain it for me. Thank you.
-
Code Wiget almost 5 yearsIf your text field is multiple lines, this makes the placeholder text centered and supercedes textAlignment = .left and contentVerticalAlignment = .top
-
Massmaker over 4 yearstry the same code but with colored -left- and -right- views on iOS 13 and build it with xCode 11 .... )) you will be surprised about how the textView changes it`s insets and hot it moves the views towards the edges so the added views are not fully visible
-
J A S K I E R over 4 yearsSwift 5: textField.layoutMargins.left = 20
-
Innocent over 4 yearshow to set in UILabel ?
-
logan.Nguyen about 4 yearsI think it mean extension UITextField for the function, singleton for this helper func is not good
-
Fattie about 4 yearsIF YOU ALSO NEED AN ICON ON THE LEFT: stackoverflow.com/a/61870553/294884 full solution to copy paste
-
Fabio about 4 years@JoséRaúlToledanoR THX :)
-
Carlo about 4 yearsElegant. Thank you.
-
Fabio about 4 years@Carlo Grazie mille Carlo :)
-
Sylvain almost 4 yearsThis solution is much cleaner than the subclassing mentioned above. Subclassing should be avoided as much as possible. I suggest the following reading krakendev.io/blog/subclassing-can-suck-and-heres-why
-
Ali Pacman about 3 yearsThis does not exist. I think you are using an extension mentioned below to achieve this.
-
zslavman about 3 yearsbe careful, this will prevent the clearButton from being displayed (if you using it)
-
Narasimha Nallamsetty almost 3 yearsThis is the best solution.