缩进UITextField中的文本


77

我的问题和标题一样简单,但还有更多一点:

我有一个UITextField,在上面设置了背景图片。问题在于文本紧靠其边缘(也就是图像的边缘)。我希望我的文本字段看起来像Apple的文本字段,在背景图像和文本的起始位置之间留出一定的水平空间。


1
您是要设置文字的插图吗?然后尝试这个问题:stackoverflow.com/questions/2694411/text-inset-for-uitextfield
phi

您可以添加带有图像的UIImageView,在其顶部添加文本字段,并相应地设置文本字段的宽度...这就是最简单的解决方案...
Swapnil Luktuke 2011年

@lukya除非他希望文本字段的可轻击区域将部分包含在图像中,否则在这种情况下,您的方法将需要一个额外的手势识别器和一些代码才能使其工作。
Mark Amery 2013年

Answers:


233

这是我不做任何子类就发现的最快方法:

UIView *spacerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
[textfield setLeftViewMode:UITextFieldViewModeAlways];
[textfield setLeftView:spacerView];

在Swift中:

let spacerView = UIView(frame:CGRect(x:0, y:0, width:10, height:10))
textField.leftViewMode = UITextFieldViewMode.Always
textField.leftView = spacerView

18
这比子分类更干净,并且可以正确处理清除按钮。希望我能给+2。
林布兰特·爱因斯坦

8
我同意,如果可以的话,+ 2。一旦我在备受
争议的

6
伟大的解决方案,将其翻译为Swift: var spacerView = UIView(frame:CGRect(x:0, y:0, width:10, height:10)); textfield.leftViewMode = UITextFieldViewMode.Always textfield.leftView = spacerView
juliensaad 2015年

2
@jsiodtb我试图在Swift中使用它,但是它阻止了我的segue的执行。知道为什么吗?我正在打电话viewDidLoad()。在中也不起作用viewWillAppear()
IIllIIll 2015年

1
@Arcrammer不允许使用与填充相同的视图两次(这将导致您描述的错误)
Norman

41

您必须继承并重写textRectForBounds:和editRectForBounds:。这是一个具有自定义背景以及垂直和水平填充的UITextfield子类:

@interface MyUITextField : UITextField 
@property (nonatomic, assign) float verticalPadding;
@property (nonatomic, assign) float horizontalPadding;
@end

#import "MyUITextField.h"
@implementation MyUITextField
@synthesize horizontalPadding, verticalPadding;
- (CGRect)textRectForBounds:(CGRect)bounds {
    return CGRectMake(bounds.origin.x + horizontalPadding, bounds.origin.y + verticalPadding, bounds.size.width - horizontalPadding*2, bounds.size.height - verticalPadding*2);
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
    return [self textRectForBounds:bounds];
}
@end

用法:

UIImage *bg = [UIImage imageNamed:@"textfield.png"];
CGRect rect = CGRectMake(0, 0, bg.size.width, bg.size.height);
MyUITextField *textfield = [[[MyUITextField alloc] initWithFrame:rect] autorelease];
textfield.verticalPadding = 10; 
textfield.horizontalPadding = 10;
[textfield setBackground:bg];
[textfield setBorderStyle:UITextBorderStyleNone];
[self.view addSubview:textfield];

1
这是一个很好的解决方案,但是当它显示时,它不考虑清除按钮。但是+1。
jweyrich

很棒的解决方案!不能相信Apple不允许您为UITextField设置插图!
RPM

@RPM由于iOS 6.0 UITextView具有attributedText属性,因此您可以将NSAttributedString设置为NSMutableParagraphStyle + firstLineHeadIndent属性(以及clear按钮的tailIndent属性)。但是,是的,它需要的iOS 6
Jano的

无论出于何种原因,内NSParagraphStyle firstLineHeadIndent似乎有在路上的文本没有影响显示在UITextField,用于iOS的6
威廉Jockusch

26

向UITextField添加填充的一种好方法是子类UITextField,重写矩形方法并添加edgeInsets属性。然后可以设置edgeInsets,并相应地绘制UITextField。使用自定义的leftView或rightView集也可以正常运行。

OSTextField.h

#import <UIKit/UIKit.h>

@interface OSTextField : UITextField

@property (nonatomic, assign) UIEdgeInsets edgeInsets;

@end

OSTextField.m

#import "OSTextField.h"

@implementation OSTextField

- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        self.edgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
    }
    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if(self){
        self.edgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
    }
    return self;
}

- (CGRect)textRectForBounds:(CGRect)bounds {
    return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds, self.edgeInsets)];
}

- (CGRect)editingRectForBounds:(CGRect)bounds {
    return [super editingRectForBounds:UIEdgeInsetsInsetRect(bounds, self.edgeInsets)];
}

@end

良好而干净的方法。只是为了向其他阅读此注释的人说明:倾向于使用spaceView并为文本视图分配leftView,但是当您有很多文本字段时,是否会通过向所有textField添加spaceViews来复制代码呢?可能不行,如果您有许多文本字段,请进行子分类。
Centurion

3
干净的解决方案。使用+1UIEdgeInsets绝对是完成当前任务的合适工具!
t6d

这行得通,如果那些UITextField使用自动布局,我发现崩溃的可接受答案。
elliotrock 2014年

IMO比投票最多的答案干净得多。不错的工作。
Brian Sachetta 2015年

我尝试了其他解决方案,它们也起作用,但是textRectForBounds是正确的方法。谢谢布罗迪。
seymatanoglu,2016年

13

我把它变成了一个很好的小扩展,可以在Storyboard中使用:

public extension UITextField {
    @IBInspectable public var leftSpacer:CGFloat {
        get {
            return leftView?.frame.size.width ?? 0
        } set {
            leftViewMode = .Always
            leftView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
        }
    }
}

1
这是完美的作品。如果将其与@IBDesignable一起使用,则可以在情节
提要中

4

我的2美分:

class PaddedTextField : UITextField {
    var insets = UIEdgeInsets.zero
    var verticalPadding:CGFloat = 0
    var horizontalPadding:CGFloat = 0

    override func textRect(forBounds bounds: CGRect) -> CGRect {
        return CGRect(x: bounds.origin.x + insets.left, y: bounds.origin.y + insets.top, width: bounds.size.width - (insets.left + insets.right), height: bounds.size.height - (insets.top + insets.bottom));
    }

    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return textRect(forBounds: bounds)
    }
}

1

建议您将转换UITextFieldUITextView并设置contentInset。例如缩进10个空格:

textview.contentInset=UIEdgeInsetsMake(0, 10, 0, 0);

这实际上是一个很好的解决方案,不确定为什么会被否决。
Jeremie D

2
@Jeremie,因为这不能回答问题。UITextField和UITextView的行为有所不同,您必须对文本视图进行重大修改才能使其像文本字段一样工作
Chris

0

有时,textField的leftView是Apple的放大镜图像。如果是这样,您可以像这样设置缩进:

    UIView *leftView = textField.leftView;
    if (leftView && [leftView isKindOfClass:[UIImageView class]]) {
        leftView.contentMode = UIViewContentModeCenter;
        leftView.width = 20.0f;  //the space you want indented.
    }

0

如果您不想创建@IBOutlet,可以简单地子类化(在Swift中为答案):

class PaddedTextField: UITextField {

  override func awakeFromNib() {
      super.awakeFromNib()

      let spacerView = UIView(frame:CGRect(x: 0, y: 0, width: 10, height: 10))
      leftViewMode = .always
      leftView = spacerView
   }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.