Create space at the beginning of a UITextField

167,508

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     
        }
    }
}
Share:
167,508

Related videos on Youtube

LinusGeffarth
Author by

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, 2021

Comments

  • LinusGeffarth
    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
      Grady Player almost 10 years
      well, 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/Swi‌​ft/…
    • ipalibowhyte
      ipalibowhyte almost 10 years
      This 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
      Grady Player almost 10 years
      the padding view would just be a vanilla UIView that has the width that you would like
    • J A S K I E R
      J A S K I E R over 4 years
      For Swift 5: textField.layoutMargins.left = 20
  • Haagenti
    Haagenti over 9 years
    This 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
    Haagenti over 9 years
    if left is 25 width should be minus 50 to have equal padding
  • Ash
    Ash about 9 years
    Why 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
    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
    Mobile Dan about 8 years
    Apple provides the equivalent of the newBounds method with the UIEdgeInsetsInsetRect function. Instead of return self.newBounds(bounds) you could use return UIEdgeInsetsInsetRect(bounds, padding) and remove the newBounds method.
  • Avaan
    Avaan about 8 years
    if 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
    justNate almost 8 years
    This does not seem to work with textField.clearButtonMode = UITextFieldViewMode.Always – the clear button is moved to the right as well
  • Nermin Sehic
    Nermin Sehic over 7 years
    Excellent 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
    Peter Kreinz over 7 years
    Great! 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
    xdev over 7 years
    Does not work when Clear button needs to be shown...the clear button is moved as well.
  • Haagenti
    Haagenti about 7 years
    This 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
    hasan over 6 years
    One 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
    Tal over 6 years
    It'd be safer to do rightView?.frame.size.width ?? 0
  • Teodor Ciuraru
    Teodor Ciuraru over 6 years
    It might. I, for myself, don't ever call the getter so it doesn't bother me.
  • Miki
    Miki over 6 years
    This does not work for UITextField inside a UISearchBar. :( I need the solution that works specifically in that case :(
  • Haagenti
    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
    Teodor Ciuraru over 6 years
    Guys, I modified the methods' names from paddingLeft to paddingLeftCustom 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
    Sharkes Monken about 5 years
    Shouldn't extension work better rather than introducing a shared class for such a minor task ?
  • Naresh
    Naresh about 5 years
    @ Sharkes Monken , I con't understood
  • Naresh
    Naresh about 5 years
    @ Sharkes Monken, can u please explain it for me. Thank you.
  • Code Wiget
    Code Wiget almost 5 years
    If your text field is multiple lines, this makes the placeholder text centered and supercedes textAlignment = .left and contentVerticalAlignment = .top
  • Massmaker
    Massmaker over 4 years
    try 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
    J A S K I E R over 4 years
    Swift 5: textField.layoutMargins.left = 20
  • Innocent
    Innocent over 4 years
    how to set in UILabel ?
  • logan.Nguyen
    logan.Nguyen about 4 years
    I think it mean extension UITextField for the function, singleton for this helper func is not good
  • Fattie
    Fattie about 4 years
    IF YOU ALSO NEED AN ICON ON THE LEFT: stackoverflow.com/a/61870553/294884 full solution to copy paste
  • Fabio
    Fabio about 4 years
    @JoséRaúlToledanoR THX :)
  • Carlo
    Carlo about 4 years
    Elegant. Thank you.
  • Fabio
    Fabio about 4 years
    @Carlo Grazie mille Carlo :)
  • Sylvain
    Sylvain almost 4 years
    This 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
    Ali Pacman about 3 years
    This does not exist. I think you are using an extension mentioned below to achieve this.
  • zslavman
    zslavman about 3 years
    be careful, this will prevent the clearButton from being displayed (if you using it)
  • Narasimha Nallamsetty
    Narasimha Nallamsetty almost 3 years
    This is the best solution.