Skip to content

Instantly share code, notes, and snippets.

@ksmandersen
Last active July 18, 2024 09:44
Show Gist options
  • Save ksmandersen/e2d4d6bd60a685e94eb7e22b7670d2a8 to your computer and use it in GitHub Desktop.
Save ksmandersen/e2d4d6bd60a685e94eb7e22b7670d2a8 to your computer and use it in GitHub Desktop.
Best way to inset text inside a UITextField
import UIKit
open class PaddedTextField: UITextField {
public var textInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) {
didSet { setNeedsDisplay() }
}
public override init(frame: CGRect) {
super.init(frame: frame)
}
convenience init() {
self.init(frame: .zero)
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
open override func textRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, textInsets)
}
open override func editingRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, textInsets)
}
open override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, textInsets)
}
open override func drawText(in rect: CGRect) {
super.drawText(in: UIEdgeInsetsInsetRect(rect, textInsets))
}
}
@mbogh
Copy link

mbogh commented May 23, 2017

Wouldn't it be nicer to do:

public var textInsets: UIEdgeInsets = .zero

@KevinQuisquater
Copy link

Thanks! Swift 5 update:

import UIKit

open class PaddedTextField: UITextField {
    public var textInsets = UIEdgeInsets.zero {
        didSet {
            setNeedsDisplay()
        }
    }
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    convenience init() {
        self.init(frame: .zero)
    }
    
    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    open override func textRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.inset(by: textInsets)
    }
    
    open override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.inset(by: textInsets)
    }
    
    open override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.inset(by: textInsets)
    }
    
    open override func drawText(in rect: CGRect) {
        super.drawText(in: rect.inset(by: textInsets))
    }
}

@gonzo-oin
Copy link

Swift 5 version with clear button handling

import UIKit

open class PaddedTextField: UITextField {
    public var textInsets = UIEdgeInsets.zero {
        didSet {
            setNeedsDisplay()
        }
    }

    public override init(frame: CGRect) {
        super.init(frame: frame)
    }

    convenience init() {
        self.init(frame: .zero)
    }

    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    open override func textRect(forBounds bounds: CGRect) -> CGRect {
        bounds.inset(by: textInsets)
    }

    open override func editingRect(forBounds bounds: CGRect) -> CGRect {
        bounds.inset(by: textInsets)
    }

    open override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
        bounds.inset(by: textInsets)
    }

    open override func clearButtonRect(forBounds bounds: CGRect) -> CGRect {
        super.clearButtonRect(forBounds: bounds).inset(by: textInsets)
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment