Add padding/insets to UIImage as background of UITextField - ios

I want to have the triangle on the right side of the textfield with a little padding, currently it is right at the border:
My code:
class Textfield: UITextField, UITextFieldDelegate {
func setup() {
let background = UIImage(systemName: "arrowtriangle.down.fill")
let imageView = UIImageView(image: background)
imageView.tintColor = .label
self.rightViewMode = .always
imageView.contentMode = .scaleAspectFit
self.rightView = imageView
}
}
How can I add insets so the triangle is a little bit more left?

You can override the text fields methods. Like this
class Textfield: UITextField, UITextFieldDelegate {
#IBInspectable var leftPadding : CGFloat = 0
#IBInspectable var rightPadding : CGFloat = 10
private var padding: UIEdgeInsets = UIEdgeInsets()
override func awakeFromNib() {
super.awakeFromNib()
padding = UIEdgeInsets(top: 0, left: leftPadding, bottom: 0, right: rightPadding)
setup()
}
func setup() {
let background = UIImage(systemName: "arrowtriangle.down.fill")
let imageView = UIImageView(image: background)
imageView.tintColor = .label
self.rightViewMode = .always
imageView.contentMode = .scaleAspectFit
self.rightView = imageView
}
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)
}
override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.width - 30, y: 0, width: 20 , height: bounds.height)
}
override func leftViewRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: 10, y: 0, width: 20 , height: bounds.height)
}
}

Related

UIView cut out any number of transparent holes

I want to a UIView can have any number of transparent holes. I tried UIBezierPath with UsesEvenOddFillRule to be true. But there is no luck, with one hole is OK, with any number of holes, it doesn't work.
You can draw a circles/ellipse with below code:
class HolyView: UIView {
var holes: [CGRect] = [] {
didSet {
setNeedsDisplay()
}
}
override func draw(_ rect: CGRect) {
super.draw(rect)
for hole in holes {
let intersection = rect.intersection(hole)
let context = UIGraphicsGetCurrentContext()
if intersection.intersects(rect) {
context?.setFillColor(self.backgroundColor?.cgColor ?? UIColor.clear.cgColor)
context?.setBlendMode(CGBlendMode.clear)
context?.fillEllipse(in: intersection)
}
}
}
}
OR Using BezierPath:
class BeziHolyView: UIView {
var holes: [CGRect] = [] {
didSet {
setNeedsDisplay()
}
}
override func draw(_ rect: CGRect) {
super.draw(rect)
let context = UIGraphicsGetCurrentContext()
context?.clear(rect)
let clipPath = UIBezierPath(rect: self.bounds)
for hole in holes {
clipPath.append(UIBezierPath(roundedRect: hole, cornerRadius: hole.height/2))
}
clipPath.usesEvenOddFillRule = true
clipPath.addClip()
backgroundColor?.setFill()
clipPath.fill()
}
}
Usage:
let view = HolyView/BeziHolyView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
view.backgroundColor = UIColor.green
view.holes = [CGRect(x: 40, y: 20, width: 20, height: 20),
CGRect(x: 80, y: 30, width: 20, height: 20)]
Result:

UITextField Standard Style programmatically

When I create a UITextField using storyboard, it looks like the image below. However, when I create a UITextField programmatically it has absolutely no style. I know that I can apply custom styles to the text field, but is there an easy way to get this standard style when creating the text field programmatically?
Something like this:
let t = UITextField()
t.frame = CGRect(x: 10, y: 20, width: self.view.frame.width - 20, height: 40)
t.layer.cornerRadius = 5
t.layer.borderColor = UIColor.lightGray.cgColor
t.layer.borderWidth = 1
t.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: t.frame.height))
t.leftViewMode = .always
t.rightView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: t.frame.height))
t.rightViewMode = .always
t.clearButtonMode = .whileEditing
self.view.addSubview(t)
EDIT:
Add this class below somewhere such that it is easily / globally accessible.
class StyledTextField: UITextField {
override init(frame: CGRect) {
super.init(frame: frame)
self.layer.cornerRadius = 5
self.layer.borderColor = UIColor.lightGray.cgColor
self.layer.borderWidth = 1
self.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: t.frame.height))
self.leftViewMode = .always
self.rightView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: t.frame.height))
self.rightViewMode = .always
self.clearButtonMode = .whileEditing
}
}
Then you can call this UITextField from where ever you want as follows
let t = StyledTextField()
t.frame = CGRect(x: 10, y: 20, width: self.view.frame.width - 20, height: 40)
self.view.addSubview(t)
EDIT 2:
Use UIEdgeInsets to get padding on all four sides.
class StyledTextField: UITextField {
let insetConstant = UIEdgeInsets(top: 4, left: 10, bottom: 4, right: 10)
override func textRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, insetConstant)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, insetConstant)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, insetConstant)
}
override init(frame: CGRect) {
super.init(frame: frame)
self.layer.cornerRadius = 5
self.layer.borderColor = UIColor(white: 2/3, alpha: 0.5).cgColor
self.layer.borderWidth = 1
self.clearButtonMode = .whileEditing
self.keyboardType = UIKeyboardType.decimalPad
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
You can add borderStyle as .roundedRect and use White background. Something like this:
class MyCustmUITextField: UITextField {
override init(frame: CGRect) {
super.init(frame: frame)
self.borderStyle = .roundedRect
self.backgroundColor = .white
}
}
You can create a subclass from UITextField to serve as your custom text field.
Following this, you need only to instantiate your custom class and then you're good to go.
Something like this:
class MyCustmUITextField: UITextField {
override init(frame: CGRect) {
super.init(frame: frame)
self.layer.cornerRadius = 5
self.layer.borderColor = UIColor.black
self.font = UIFont.systemFont(ofSize: 20)
self.adjustsFontSizeToFitWidth = true
// then add whatever styles you wish
}
}
From there all you need is to create a new instance of MyCustomUITextField

UILabel border and padding

I want to add padding inside my label in order to have spaces between it and its border. I created for that a class that extends from UILabel.
UILabelPadding.swift:
import UIKit
class UILabelPadding: UILabel {
let padding = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 30)
override func drawText(in rect: CGRect) {
super.drawText(in: UIEdgeInsetsInsetRect(rect, padding))
}
override var intrinsicContentSize : CGSize {
let superContentSize = super.intrinsicContentSize
let width = superContentSize.width + padding.left + padding.right
let heigth = superContentSize.height + padding.top + padding.bottom
return CGSize(width: width, height: heigth)
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
let superSizeThatFits = super.sizeThatFits(size)
let width = superSizeThatFits.width + padding.left + padding.right
let heigth = superSizeThatFits.height + padding.top + padding.bottom
return CGSize(width: width, height: heigth)
}
}
and I changed the type of myLabel from UILabel to UILabelPadding. In my UIViewController, I set the text of myLabel, call the sizeToFit() and after that I add the border and the background color to myLabel:
myLabel.text = "label test"
myLabel.sizeToFit()
//background + border
myLabel.layer.borderColor = UIColor(red: 27/255, green: 100/255, blue: 90/255, alpha: 1.0).cgColor
myLabel.layer.backgroundColor = UIColor(red: 27/255, green: 100/255, blue: 90/255, alpha: 1.0).cgColor
myLabel.layer.cornerRadius = 9
myLabel.layer.masksToBounds = true
myLabel.layer.borderWidth = 1
The border and the background color are added but the padding is not working. When I debug, the sizeThatFits() is never called.
Any help please?
I solved the issue!
For those how are facing the same problem:
1- Make a class extending from UILabel:
UILabelPadding.swift:
class UILabelPadding: UILabel {
let padding = UIEdgeInsets(top: 2, left: 8, bottom: 2, right: 8)
override func drawText(in rect: CGRect) {
super.drawText(in: rect.inset(by: padding))
}
override var intrinsicContentSize : CGSize {
let superContentSize = super.intrinsicContentSize
let width = superContentSize.width + padding.left + padding.right
let heigth = superContentSize.height + padding.top + padding.bottom
return CGSize(width: width, height: heigth)
}
}
2- Set the type of your label to the UILabelPadding and make sure that the type is set also in the storyboard.
I use a label subclass that does much what you describe. It looks like this:
class MyBoundedLabel: UILabel {
override func drawText(in rect: CGRect) {
let context = UIGraphicsGetCurrentContext()!
context.stroke(self.bounds.insetBy(dx: 1.0, dy: 1.0))
super.drawText(in: rect.insetBy(dx: 5.0, dy: 5.0))
}
}
You might try that, and then jiggle the numbers and other details so they look like what you want.
I have used this solution in my app. Please check below codes.
class CustomLabel: UILabel {
var textInsets = UIEdgeInsets.zero {
didSet { invalidateIntrinsicContentSize() }
}
override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
let invertedInsets = UIEdgeInsets(top: -textInsets.top,
left: -textInsets.left,
bottom: -textInsets.bottom,
right: -textInsets.right)
return textRect.inset(by: invertedInsets)
}
override func drawText(in rect: CGRect) {
super.drawText(in: rect.inset(by: textInsets))
}
}

Adding Padding to UITextField [duplicate]

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.
This is what I am using right now:
Swift 4.2, 5
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;
}
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.
X, Y , Z are your desired values
textField.layer.sublayerTransform = CATransform3DMakeTranslation(x, y, z)
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...
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
}
}
}
Use my extension Swift 5 tested:
extension UITextField {
enum PaddingSpace {
case left(CGFloat)
case right(CGFloat)
case equalSpacing(CGFloat)
}
func addPadding(padding: PaddingSpace) {
self.leftViewMode = .always
self.layer.masksToBounds = true
switch padding {
case .left(let spacing):
let leftPaddingView = UIView(frame: CGRect(x: 0, y: 0, width: spacing, height: self.frame.height))
self.leftView = leftPaddingView
self.leftViewMode = .always
case .right(let spacing):
let rightPaddingView = UIView(frame: CGRect(x: 0, y: 0, width: spacing, height: self.frame.height))
self.rightView = rightPaddingView
self.rightViewMode = .always
case .equalSpacing(let spacing):
let equalPaddingView = UIView(frame: CGRect(x: 0, y: 0, width: spacing, height: self.frame.height))
// left
self.leftView = equalPaddingView
self.leftViewMode = .always
// right
self.rightView = equalPaddingView
self.rightViewMode = .always
}
}
}
How to use
// equal padding
yourTextField.addPadding(padding: .equalSpacing(10))
// padding right
yourTextField.addPadding(padding: .right(10))
// padding left
yourTextField.addPadding(padding: .left(10))
in Swift 4.2 and Xcode 10
Initially my text field is like this.
After adding padding in left side my text field is...
//Code for left padding
textFieldName.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: textFieldName.frame.height))
textFieldName.leftViewMode = .always
Like this we can create right side also.(textFieldName.rightViewMode = .always)
If you want SharedInstance type code(Write once use every ware) see the below code.
//This is my shared class
import UIKit
class SharedClass: NSObject {
static let sharedInstance = SharedClass()
//This is my padding function.
func textFieldLeftPadding(textFieldName: UITextField) {
// Create a padding view
textFieldName.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 3, height: textFieldName.frame.height))
textFieldName.leftViewMode = .always//For left side padding
textFieldName.rightViewMode = .always//For right side padding
}
private override init() {
}
}
Now call this function like this.
//This single line is enough
SharedClass.sharedInstance.textFieldLeftPadding(textFieldName:yourTF)
Simple swift 3 solution - add code to viewDidLoad:
let indentView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 20))
textField.leftView = indentView
textField.leftViewMode = .always
No need for ridiculously long code
Here is Haagenti's answer updated to Swift 4.2:
class PaddedTextField: UITextField {
func getPadding(plusExtraFor clearButtonMode: ViewMode) -> UIEdgeInsets {
var padding = UIEdgeInsets(top: 11, left: 16, bottom: 11, right: 16)
// Add additional padding on the right side when showing the clear button
if self.clearButtonMode == .always || self.clearButtonMode == clearButtonMode {
padding.right = 28
}
return padding
}
override open func textRect(forBounds bounds: CGRect) -> CGRect {
let padding = getPadding(plusExtraFor: .unlessEditing)
return bounds.inset(by: padding)
}
override open func placeholderRect(forBounds bounds: CGRect) -> CGRect {
let padding = getPadding(plusExtraFor: .unlessEditing)
return bounds.inset(by: padding)
}
override open func editingRect(forBounds bounds: CGRect) -> CGRect {
let padding = getPadding(plusExtraFor: .whileEditing)
return bounds.inset(by: padding)
}
}
Reference: Upgrading To Swift 4.2.
Edit: Account for clear button.
To create padding view for UITextField in Swift 5
func txtPaddingVw(txt:UITextField) {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 5))
txt.leftViewMode = .always
txt.leftView = paddingView
}
This one line of code saved me:
For Xamarin.iOS:
textField.Layer.SublayerTransform = CATransform3D.MakeTranslation(5, 0, 0);
For Swift:
textField.layer.sublayerTransform = CATransform3DMakeTranslation(5, 0, 0);
Subclassing UITextField is the way to go. Open a playground and add the following code:
class MyTextField : UITextField {
var leftTextMargin : CGFloat = 0.0
override func textRectForBounds(bounds: CGRect) -> CGRect {
var newBounds = bounds
newBounds.origin.x += leftTextMargin
return newBounds
}
override func editingRectForBounds(bounds: CGRect) -> CGRect {
var newBounds = bounds
newBounds.origin.x += leftTextMargin
return newBounds
}
}
let tf = MyTextField(frame: CGRect(x: 0, y: 0, width: 100, height: 44))
tf.text = "HELLO"
tf.leftTextMargin = 25
tf.setNeedsLayout()
tf.layoutIfNeeded()
Easy way: to do this by extending UITextField
extension UITextField {
func setPadding(left: CGFloat? = nil, right: CGFloat? = nil){
if let left = left {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: left, height: self.frame.size.height))
self.leftView = paddingView
self.leftViewMode = .always
}
if let right = right {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: right, height: self.frame.size.height))
self.rightView = paddingView
self.rightViewMode = .always
}
}
}
Then you can set padding to any edge this way:
textField.setPadding(left: 5, right: 5)
In most cases you can regard this as a technicality but all the examples don't get the difference between frame and bounds right. When referencing the view's height in a subview, use bounds – otherwise you may run into trouble once some transform is applied to the parent.
See the updated code below (based on Pheepster's answer).
extension UITextField {
func setLeftPadding(_ amount: CGFloat = 10) {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.bounds.size.height))
self.leftView = paddingView
self.leftViewMode = .always
}
func setRightPadding(_ amount: CGFloat = 10) {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.bounds.size.height))
self.rightView = paddingView
self.rightViewMode = .always
}
}
Create UIView with required padding space and add it to textfield.leftView member and set textfield.leftViewMode member to UITextFieldViewMode.Always
// For example if you have textfield named title
#IBOutlet weak var title: UITextField!
// Create UIView
let paddingView : UIView = UIView(frame: CGRectMake(0, 0, 5, 20))
//Change your required space instaed of 5.
title.leftView = paddingView
title.leftViewMode = UITextFieldViewMode.Always
I prefer to use IBDesignable class and IBInspectable properties to allow me to set the padding via Xcode storyboards and keep it reusable. I've also updated the code to work in Swift 4.
import Foundation
import UIKit
#IBDesignable
class PaddableTextField: UITextField {
var padding = UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)
#IBInspectable var left: CGFloat = 0 {
didSet {
adjustPadding()
}
}
#IBInspectable var right: CGFloat = 0 {
didSet {
adjustPadding()
}
}
#IBInspectable var top: CGFloat = 0 {
didSet {
adjustPadding()
}
}
#IBInspectable var bottom: CGFloat = 0 {
didSet {
adjustPadding()
}
}
func adjustPadding() {
padding = UIEdgeInsets(top: top, left: left, bottom: bottom, right: right)
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
}
override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: UIEdgeInsets(top: top, left: left, bottom: bottom, right: right))
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: UIEdgeInsets(top: top, left: left, bottom: bottom, right: right))
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: UIEdgeInsets(top: top, left: left, bottom: bottom, right: right))
}
}
Put this code in your viewDidLoad():
textField.delegate = self
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: self.textField.frame.height))
textField.leftView = paddingView
textField.leftViewMode = UITextFieldViewMode.always
It works for me :)
ScareCrow's answer in Swift 3
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)
}
In Swift 3.
You may use custom UITextField with indent that is set in its constructor. Don't need for extra declaration in a controller.
class CustomTextField : UITextField {
private let indentView = UIView(frame: CGRect(x: 0, y:0, width: 10, height: 10))
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.leftView = indentView
self.leftViewMode = .always
}
}
* Extending UITextField in Swift 5 *
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
}
}
}
//MARK:- Use this class for different type of Roles
import UIKit
class HelperExtensionViewController: UIViewController {
}
//MARK:- Extension
extension UIImageView
{
func setImageCornerRadius()
{
self.layer.cornerRadius = self.frame.size.height/2
self.clipsToBounds = true
}
func setImageCornerRadiusInPoints(getValue:CGFloat)
{
self.layer.cornerRadius = getValue
self.clipsToBounds = true
}
}
extension UIButton
{
func setButtonCornerRadiusOnly()
{
self.layer.cornerRadius = self.frame.size.height/2
self.clipsToBounds = true
}
func setBtnCornerRadiusInPoints(getValue:CGFloat)
{
self.layer.cornerRadius = getValue
self.clipsToBounds = true
}
}
extension UITextField
{
func setTextFieldCornerRadiusWithBorder()
{
self.layer.cornerRadius = self.frame.size.height/2
self.layer.borderColor = UIColor.darkGray.cgColor
self.backgroundColor = UIColor.clear
self.layer.borderWidth = 0.5
self.clipsToBounds = true
}
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
}
}
extension UIView
{
func setCornerRadius()
{
self.layer.cornerRadius = self.frame.size.height/2
self.clipsToBounds = true
}
// OUTPUT 1
func setViewCornerRadiusWithBorder()
{
self.layer.cornerRadius = self.frame.size.height/2
self.layer.borderColor = UIColor.init(red: 95.0/255.0, green: 229.0/255.0, blue: 206.0/255.0, alpha: 1.0).cgColor
self.backgroundColor = UIColor.clear
self.layer.borderWidth = 1.0
self.clipsToBounds = true
}
func layoutSubviews(myView:UIView)
{
let shadowPath = UIBezierPath(rect: myView.bounds)
myView.layer.masksToBounds = false
myView.layer.shadowColor = UIColor.lightGray.cgColor
myView.layer.shadowOffset = CGSize(width: -1.0, height: 2.0)
myView.layer.shadowOpacity = 0.5
myView.layer.shadowPath = shadowPath.cgPath
}
func layoutSubviews2(myView:UIView)
{
let shadowPath = UIBezierPath(rect: myView.bounds)
myView.clipsToBounds = true
myView.layer.masksToBounds = false
myView.layer.shadowColor = UIColor.black.cgColor
myView.layer.shadowOffset = CGSize(width: 0.0, height: 1.0)
myView.layer.shadowOpacity = 0.2
myView.layer.shadowPath = shadowPath.cgPath
}
func setViewCornerRadiusInPoints(getValue:CGFloat)
{
self.layer.cornerRadius = getValue
self.clipsToBounds = true
}
func dropShadow(scale: Bool = true) {
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.5
layer.shadowOffset = CGSize(width: -1, height: 1)
layer.shadowRadius = 1
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = scale ? UIScreen.main.scale : 1
}
// OUTPUT 2
func dropShadow(color: UIColor, opacity: Float = 0.5, offSet: CGSize, radius: CGFloat = 1, scale: Bool = true) {
layer.masksToBounds = false
layer.shadowColor = color.cgColor
layer.shadowOpacity = opacity
layer.shadowOffset = offSet
layer.shadowRadius = radius
layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = scale ? UIScreen.main.scale : 1
}
func setGradientBackground(myview:UIView) {
let colorTop = UIColor(red: 100.0/255.0, green: 227.0/255.0, blue: 237.0/255.0, alpha: 1.0).cgColor
let colorBottom = UIColor(red: 141.0/255.0, green: 109.0/255.0, blue: 164.0/255.0, alpha: 1.0).cgColor
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [colorTop, colorBottom]
gradientLayer.locations = [1.0, 1.0]
gradientLayer.frame = myview.bounds
myview.layer.insertSublayer(gradientLayer, at:0)
}
}
To Extend original answer for leftView and Swift5+
class TextField: UITextField {
let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
override open func textRect(forBounds bounds: CGRect) -> CGRect {
let paddedRect = bounds.inset(by: self.padding)
if (self.leftViewMode == .always || self.leftViewMode == .unlessEditing) {
return self.adjustRectOriginForLeftView(bounds: paddedRect)
}
return paddedRect
}
override open func placeholderRect(forBounds bounds: CGRect) -> CGRect {
let paddedRect = bounds.inset(by: self.padding)
if (self.leftViewMode == .always || self.leftViewMode == .unlessEditing) {
return self.adjustRectOriginForLeftView(bounds: paddedRect)
}
return paddedRect;
}
override open func editingRect(forBounds bounds: CGRect) -> CGRect {
let paddedRect = bounds.inset(by: self.padding);
if (self.leftViewMode == .always || self.leftViewMode == .unlessEditing) {
return self.adjustRectOriginForLeftView(bounds: paddedRect)
}
return paddedRect;
}
func adjustRectOriginForLeftView(bounds : CGRect) -> CGRect{
var paddedRect = bounds;
paddedRect.origin.x += self.leftView!.frame.width
return paddedRect
}
}
Create space at the beginning of a UITextField.
in Swift 5+ and Xcode 12.
textFieldName.setLeftPaddingPoints(CGFloat(10))
textFieldName.setRightPaddingPoints(CGFloat(10)

set the padding of a text field using swift in xcode

How to create some space at the beginning of a text field using swift?
I looked at the post
padding of text field
I don't understand what the subclass is doing and how do I use that class to padding.
Thank you very much
https://stackoverflow.com/a/27066764/846780
This answer is very clear,
If you subclass UITextField you can override textRectForBounds, editingRectForBounds and placeholderRectForBounds. These methods just allow you to add a rect (frame) to your textfield's label.
newBounds method create the rect (frame) that will be added to textfield's label.
Finally your padding is: let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5);
Now you have a custom UITextField that has a custom padding.
If you create your new subClass like this class MyTextField: UITextField for example, you only need to change the class of the UITextField that you've added into IB file.
Complementing the answer of klevison-matias this is the code I use when I want to add a padding to my TextField in Swift 3
//UITextField : override textRect, editingRect
class LeftPaddedTextField: UITextField {
override func textRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + 10, y: bounds.origin.y, width: bounds.width, height: bounds.height)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + 10, y: bounds.origin.y, width: bounds.width, height: bounds.height)
}
}
Then in my TextField I use in this way:
let emailTextField: LeftPaddedTextField = {
let textField = LeftPaddedTextField()
textField.placeholder = "Enter email"
textField.layer.borderColor = UIColor.lightGray.cgColor
textField.layer.borderWidth = 1
textField.keyboardType = .emailAddress
return textField
}()
let passwordTextField: LeftPaddedTextField = {
let textField = LeftPaddedTextField()
textField.placeholder = "Enter password"
textField.layer.borderColor = UIColor.lightGray.cgColor
textField.layer.borderWidth = 1
textField.isSecureTextEntry = true
return textField
}()
Create TextField outlet and use following code. Say "nameTextField" has to add padding.
let paddingView = UIView(frame: CGRectMake(x: 0, y: 0, width: 30, height: 30))
nameTextField.leftView = paddingView
nameTextField.leftViewMode = .always
nameTextField.placeholder = "Enter Name"
You can add Image in paddingView.
Based on #Jorge Casariego's answer I came up with this solution.
You can set PaddedTextField class and the desired padding through the Interface Builder!
class PaddedTextField: UITextField {
#IBInspectable var padding: CGFloat = 0
override func textRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + padding, y: bounds.origin.y, width: bounds.width - padding * 2, height: bounds.height)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + padding, y: bounds.origin.y, width: bounds.width - padding * 2, height: bounds.height)
}
}
full code sample:
make sure your TextField points to RoundedTextField via Story board
import UIKit
class RoundedTextField: UITextField {
override func awakeFromNib() {
// add rounded corner
self.layer.cornerRadius = 15.0
self.clipsToBounds = false
super.awakeFromNib()
}
// For the padding from the left
override func textRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + 15.0, y: bounds.origin.y, width: bounds.width, height: bounds.height)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + 15.0, y: bounds.origin.y, width: bounds.width, height: bounds.height)
}
}

Resources