Add lefthand margin to UITextField
Asked Answered
U

9

27

I want to put the left margin of a UITextField's text at 10 px. What is the best way to do that?

Urquhart answered 15/4, 2011 at 9:13 Comment(1)
For more detailed answer of this question refer this answer #3727568Engud
J
21

As I have explained in a previous comment, the best solution in this case is to extend the UITextField class instead of using a category, so you can use it explicitly on the desired text fields.

#import <UIKit/UIKit.h>

@interface MYTextField : UITextField

@end


@implementation MYTextField

- (CGRect)textRectForBounds:(CGRect)bounds {
    int margin = 10;
    CGRect inset = CGRectMake(bounds.origin.x + margin, bounds.origin.y, bounds.size.width - margin, bounds.size.height);
    return inset;
}

- (CGRect)editingRectForBounds:(CGRect)bounds {
    int margin = 10;
    CGRect inset = CGRectMake(bounds.origin.x + margin, bounds.origin.y, bounds.size.width - margin, bounds.size.height);
    return inset;
}

@end

A category is intended to add new functions to an existing class, not to override an existing method.

Julio answered 28/3, 2012 at 5:3 Comment(3)
One question. How can I use this new extended class from Storyboard or Interface Builder? Thanks a lot.Protuberant
Hi Ricardo, you need to select the element in Storyboard or Interface Builder and edit the custom class in Identity Inspector. grrrab.it/5rr3xyJulio
The methods you are overriding are doing a few things that you are not accounting for e.g. not including borders and space occupied by overlay views... so I would call through to super first, which looks like this: return CGRectInset([super textRectForBounds:bounds], 10.f, 0.f);Raucous
D
44

You can do it by extending UITextField class and overriding two methods:

- (CGRect)textRectForBounds:(CGRect)bounds;
- (CGRect)editingRectForBounds:(CGRect)bounds;

Here is the code:

The interface in MYTextField.h

@interface MYTextField : UITextField

@end

Its implementation in MYTextField.m

@implementation MYTextField

static CGFloat leftMargin = 28;

 - (CGRect)textRectForBounds:(CGRect)bounds
{
    bounds.origin.x += leftMargin;

    return bounds;
}

 - (CGRect)editingRectForBounds:(CGRect)bounds
{
    bounds.origin.x += leftMargin;

    return bounds;
}
@end
Dunbar answered 11/5, 2011 at 12:45 Comment(8)
Thanks it worked for me...But I have one issue,that it uses that for all the text fields in my application.I want that to be on particular view controllers text field.Can you help me in that.Guardafui
It's the expected behaviour of catégories, it's not the solution in this case. You have to extend UITextField and override the same methods. So use @clopez solution instead.Dunbar
First I upvoted, but then downvoted. If you add 10 px for origin, you need to subtract 20 px from the width to keep the same margin on the left and on the right. Plus overridding methods through a category is really a bad idea dude, as folks already noted above.Probe
The question is about left margin ONLY.Dunbar
what is the original bounds values for resetting?Analisaanalise
@TwiterZX it doesn't matter that they asked for "left margin only". The point is that is wrong to teach bad practices, specially ones that lead to hard bugs like overriding methods in categories.Intermit
@Intermit I know, I was not able to change it when first posted the answer, now it's doneDunbar
Just one idea to make this a one-liner: return UIEdgeInsetsInsetRect(bounds, UIEdgeInsetsMake(0, 10, 0, 0));Hague
J
21

As I have explained in a previous comment, the best solution in this case is to extend the UITextField class instead of using a category, so you can use it explicitly on the desired text fields.

#import <UIKit/UIKit.h>

@interface MYTextField : UITextField

@end


@implementation MYTextField

- (CGRect)textRectForBounds:(CGRect)bounds {
    int margin = 10;
    CGRect inset = CGRectMake(bounds.origin.x + margin, bounds.origin.y, bounds.size.width - margin, bounds.size.height);
    return inset;
}

- (CGRect)editingRectForBounds:(CGRect)bounds {
    int margin = 10;
    CGRect inset = CGRectMake(bounds.origin.x + margin, bounds.origin.y, bounds.size.width - margin, bounds.size.height);
    return inset;
}

@end

A category is intended to add new functions to an existing class, not to override an existing method.

Julio answered 28/3, 2012 at 5:3 Comment(3)
One question. How can I use this new extended class from Storyboard or Interface Builder? Thanks a lot.Protuberant
Hi Ricardo, you need to select the element in Storyboard or Interface Builder and edit the custom class in Identity Inspector. grrrab.it/5rr3xyJulio
The methods you are overriding are doing a few things that you are not accounting for e.g. not including borders and space occupied by overlay views... so I would call through to super first, which looks like this: return CGRectInset([super textRectForBounds:bounds], 10.f, 0.f);Raucous
H
13
UITextField * textField = [[UITextField alloc]init];
[textField setDelegate:self];
[textField setFrame:CGRectMake(170,112,140,25)];
[textField setBorderStyle:UITextBorderStyleNone];
[textField setBackgroundColor:[UIColor clearColor]];
[self.View addSubview:noofChildTField];

UIView *paddingView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)] autorelease];
textField.leftView = paddingView;
textField.leftViewMode = UITextFieldViewModeAlways;

Try this code

Horsehide answered 23/3, 2013 at 6:11 Comment(1)
great! thank you! just modify CGRectMake 5 to much more value if we need bigger margin.Semasiology
F
11

For Swift 3 :

Make an outlet of the UITextField, say usernameTextField. Then write the following code in viewDidLoad()

let paddingView : UIView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 20))
usernameTextField.leftView = paddingView
usernameTextField.leftViewMode = .always

Change the width: 5 to a greater value if more space is required.

Fellow answered 9/1, 2017 at 12:0 Comment(1)
This is much nicer than subclassing... :)Mining
R
5

I was hoping to see a setting in IB in the property inspector to adjust this value. Turns out I had set alignment and border style inadvertently to values that messed with the padding on the left.

You wouldn't think it would be a big deal to choose left justify and no border but it makes the words basically overlap or come right to the edge of the box and it doesn't look right.

Bad:

enter image description here

Good:

enter image description here

Fixed it right up for me. Hope this helps someone else as well.

Recuperative answered 9/3, 2016 at 16:36 Comment(2)
+1 for noticing that UITextBorderStyleRoundedRect adds a nice left padding to the TextField, whereas UITextBorderStyleNone plus your own (right-angle) border puts the text right up against the edge.Tolley
This works in essence, but has the side effect of making a light border around the control if you make your own layer borders (like rounded or oval edges); so you still need to use UITextBorderStyleNone along with padding method to get the right effect.There
D
5

Subclass the UITextField and add an extension:

extension UITextField {
    func paddingLeft(inset: CGFloat){
        self.leftView = UIView(frame: CGRect(x: 0, y: 0, width: inset, height: self.frame.height))
        self.leftViewMode = UITextField.ViewMode.always
    }
}

usage

class MyUITextFieldClass: UITextField {
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        self.paddingLeft(inset: 10)
    }
}
Deli answered 28/8, 2019 at 1:23 Comment(0)
U
1

i have reached almost by overriding - (CGRect)textRectForBounds:(CGRect)bounds. now issue is when TextField goes in to edit mode their left margin reset to Zero .......

@implementation UITextField(UITextFieldCatagory)

- (CGRect)textRectForBounds:(CGRect)bounds {
    CGRect theRect=CGRectMake(bounds.origin.x+10, bounds.origin.y, bounds.size.width-10, bounds.size.height);
    return theRect;


}
Urquhart answered 15/4, 2011 at 9:17 Comment(1)
Why not bounds.origin.y - 20 ?Filide
B
1

For Swift 4:

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))
    }
}
Beautiful answered 2/12, 2018 at 3:46 Comment(0)
C
-3

You can try this

TextField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
TextField.textAlignment = UITextAlignmentCenter;
Croner answered 15/4, 2011 at 9:17 Comment(1)
This is not answering the questionHarbaugh

© 2022 - 2024 — McMap. All rights reserved.