UITextField的文本插入?


Answers:


628

覆盖-textRectForBounds:只会更改占位符文本的插图。要更改可编辑文本的插图,您还需要覆盖-editingRectForBounds:

// placeholder position
- (CGRect)textRectForBounds:(CGRect)bounds {
     return CGRectInset(bounds, 10, 10);
}

// text position
- (CGRect)editingRectForBounds:(CGRect)bounds {
     return CGRectInset(bounds, 10, 10);
}

10
尽管我使用了CGRectInset(bounds,9,0)的返回值,但该解决方案对我有用。我还需要为textRectForBounds,editingRectForBounds和placeholderRectForBounds设置此值。
RyJ 2012年

2
该解决方案不能与clearButton配合使用。TextField叠加按钮内的文本。
Piotr

我认为,覆盖上述方法会导致滚动变慢(如果UITextField驻留在内)UIScrollView
巴拉特·多德佳

2
放置ClearButton的方法: - (CGRect)clearButtonRectForBounds:(CGRect)bounds { return CGRectMake(x, y, w, h); } 在这里找到:stackoverflow.com/questions/5361369/…–
Miros,

22
我建议在调用CGRectInset(bounds,10,10)之前先调用[super textRectForBounds:bounds]和[super editRectForBounds:bounds]。这将解决清除按钮覆盖的问题。
mrvincenzo

294

我能够通过以下方式做到这一点:

myTextField.layer.sublayerTransform = CATransform3DMakeTranslation(5, 0, 0);

当然,请记住导入QuartzCore并将框架添加到您的项目中。


38
为创造力+1,但这有点问题,它还会在文本字段内移动删除按钮
Nikita

2
你可以做myTextField.layer.sublayers,它是所有子层的数组...,如果它的UIImageView <-我假设X是一个图像..或者也许是UIButton ...,或者可以遍历每一个来查看其中一个属于哪个子视图...但myfield.layer.sublayerTransform所有的子层,因此X按钮移动以及..
chuthan20

此解决方案不适用于我。我只能设置“左”和“上”边距,而不能设置“右”和“下”。UITextField在其右侧重叠内容。
巴拉特·多德嘉

2
这是没有子类的最佳解决方案,并且不需要在屏幕上放置多余的不必要的视图!+1!
Rambatino 2014年

1
@ jeet.chanchawat在这张照片上右侧的X按钮.. developer.apple.com/library/content/documentation/...
chuthan20

169

如果只需要左边距,则可以尝试以下操作:

UItextField *textField = [[UITextField alloc] initWithFrame:...];
UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, textField.frame.size.height)];
leftView.backgroundColor = textField.backgroundColor;
textField.leftView = leftView;
textField.leftViewMode = UITextFieldViewModeAlways;

这个对我有用。希望对您有所帮助。


17
这远比仅获取一个内嵌子类要容易得多,它使您可以在左侧添加任何任意视图(也可以使用rightView在右侧添加一些内容)。比接受的答案好,恕我直言。
肯尼·格兰特

4
+1简单,无子类化,并且旨在与文本字段属性一起使用(而不是“ hacking”)。
因此,它

第三行应该是leftView.backgroundColor = textField.backgroundColor;...除了那个伟大的解决方案之外...谢谢(:
Aviel Gross 2013年

不如azdev的回答那么优雅/周到,但是对于常见和简单的案例来说,这是一个很好的解决方案!
林布兰特·爱因斯坦

1
子类化可以为您节省大量时间,除非您只需要一个文本框。
2015年

168

在派生自UITextField的类中,至少重写以下两个方法:

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

如果没有其他内容,它可能就是这样简单:

return CGRectInset(bounds , 10, 10);

UITextField提供了几种可以覆盖的定位方法。


2
是的,如果您不覆盖editingRectForBounds,则在文本字段左上角进行编辑时会得到文本。-(CGRect)editingRectForBounds:(CGRect)bounds {return CGRectInset(bounds,10,10); }
Mark W

1
刚编辑好答案,以将editRectForBounds方法集成到
2014年

5
在我看来,这是一个可怕的- (CGRect)borderRectForBounds:(CGRect)bounds; - (CGRect)placeholderRectForBounds:(CGRect)bounds; - (CGRect)clearButtonRectForBounds:(CGRect)bounds; - (CGRect)leftViewRectForBounds:(CGRect)bounds; - (CGRect)rightViewRectForBounds:(CGRect)bounds;
骇客

97

怎么样的@IBInspectable@IBDesignable迅速类。

@IBDesignable
class TextField: UITextField {
    @IBInspectable var insetX: CGFloat = 6 {
       didSet {
         layoutIfNeeded()
       }
    }
    @IBInspectable var insetY: CGFloat = 6 {
       didSet {
         layoutIfNeeded()
       }
    }

    // placeholder position
    override func textRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , insetX , insetY)
    }

    // text position
    override func editingRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , insetX , insetY)
    }
}

您将在情节提要中看到它。

在此处输入图片说明

更新-Swift 3

@IBDesignable
class TextField: UITextField {
    @IBInspectable var insetX: CGFloat = 0
    @IBInspectable var insetY: CGFloat = 0

    // placeholder position
    override func textRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: insetX, dy: insetY)
    }

    // text position
    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: insetX, dy: insetY)
    }
}

1
我发现对Y的影响是不希望的,我不想缩小文本的矩形,而是将其向字段的基线轻推。我将实现调整为let rect = CGRect(x: bounds.minX, y: bounds.minY + insetY, width: bounds.width, height: bounds.height) return CGRectInset(rect , insetX , 0)
克里斯·瓦格纳

1
如果您使用的是占位符,则还要添加此内容`重写func placeholderRectForBounds(bounds:CGRect)-> CGRect {return CGRectInset(bounds,insetX,insetY)}`
RameshVel

奇怪的是(在textRect/中设置插图editingRect)会在文本溢出可见矩形时影响滚动性能(至少在iOS 12上)。插入值为15时,它甚至停止滚动。
Ixx

29

如果您有一个明确的按钮,则接受的答案将对您不起作用。我们还应防止Apple将来通过致电来改变情况super

因此,为确保文本不与清除按钮重叠,让我们首先获取“默认”值super,然后根据需要进行调整。

此代码将在文本字段的顶部,左侧和底部添加一个10px的插图:

@interface InsetTextField : UITextField

@end


@implementation InsetTextField

// Placeholder position
- (CGRect)textRectForBounds:(CGRect)bounds {
    CGRect rect = [super textRectForBounds:bounds];
    UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 10, 0);

    return UIEdgeInsetsInsetRect(rect, insets);
}

// Text position
- (CGRect)editingRectForBounds:(CGRect)bounds {
    CGRect rect = [super editingRectForBounds:bounds];
    UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 10, 0);

    return UIEdgeInsetsInsetRect(rect, insets);
}

// Clear button position
- (CGRect)clearButtonRectForBounds:(CGRect)bounds {
    CGRect rect = [super clearButtonRectForBounds:bounds];

    return CGRectOffset(rect, -5, 0);
}

@end

注意:UIEdgeInsetsMake接受参数的顺序为:topleftbottomright


使用textRectForBounds:editingRectForBounds:方法,而不 clearButtonRectForBounds:在iOS 7+为我工作。
Stunner

clearButtonRectForBounds:只是有助于向左轻推清除按钮。您可能希望忽略它。我的文本字段是在深色背景上,并且清除按钮在右侧需要一些额外的填充。
克里斯·诺莱特

奇怪的是,当文本溢出可见矩形时,这会影响滚动性能(至少在iOS 12上)。插入值为15时,它甚至停止滚动。
Ixx

22

以为我会提供快速解决方案

import UIKit

class TextField: UITextField {
    let inset: CGFloat = 10

    // placeholder position
    override func textRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , inset , inset)
    }

    // text position
    override func editingRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , inset , inset)
    }

    override func placeholderRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds, inset, inset) 
    }
}

迅捷3+

import UIKit

class TextField: UITextField {
    let inset: CGFloat = 10

    // placeholder position
    override func textRect(forBounds: CGRect) -> CGRect {
        return forBounds.insetBy(dx: self.inset , dy: self.inset)
    }

    // text position
    override func editingRect(forBounds: CGRect) -> CGRect {
        return forBounds.insetBy(dx: self.inset , dy: self.inset)
    }

    override func placeholderRect(forBounds: CGRect) -> CGRect {
        return forBounds.insetBy(dx: self.inset, dy: self.inset)
    }
}

2
不要忘记 override func placeholderRectForBounds(bounds: CGRect) -> CGRect { return CGRectInset(bounds, inset, inset) }
Eugene Braginets 2015年

在Swift 3中,您必须使用'CGRect.insetBy()'方法
Den

1
至少在iOS 11中,如果您覆盖textRectForBounds,则占位符也会受到影响-因此添加占位符覆盖会使占位符再插入10pt。that,如果您要寻找的是👍🏼,但如果不是,请注意。
指定

奇怪的是,当文本溢出可见矩形时,这会影响滚动性能(至少在iOS 12上)。插入值为15时,它甚至停止滚动。
Ixx

14

使用textRectForBounds:是正确的方法。我将其包装在子类中,因此您可以简单地使用textEdgeInsets。参见SSTextField


这种方法以及使用cocoapods导入SSToolkit pod的方法非常有效-我认为这是最简单的方法。
克里斯,

谢谢克里斯!很高兴您发现它很有用。
Sam Soffes 2013年

14

迅速

 class TextField: UITextField {

    let inset: CGFloat = 8

    // placeholder position
    override func textRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: inset, dy: inset)
    }

    // text position
    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: inset, dy: inset)
    }
}

奇怪的是,当文本溢出可见矩形时,这会影响滚动性能(至少在iOS 12上)。插入值为15时,它甚至停止滚动。
Ixx

12

对于正在寻找更简单解决方案的人们。

UITextField里面添加一个UIView。为了模拟文本字段周围的插图,我保持左侧10像素,宽度比视图小20像素。对于文本框周围的圆角边框,请使用视图的边框

viewBG.layer.cornerRadius = 8.0;
viewBG.layer.borderColor = [UIColor darkGrayColor].CGColor;
viewBG.layer.borderWidth = 1.0;

2
老实说,将UIView放在UITextField后面是最好和最简单的解决方案。使UITextField透明并完成。我将其与UITextView对齐-嵌入约6个像素。比创建子类容易得多,也更灵活……
n13 2012年

这种方法的问题是滚动条将出现的位置。
道格·阿莫斯

@DougAmos什么滚动条?您是在指UITextView吗?
含义-

12

您可以通过设置leftView为UITextField设置文本插入。

像这样:

UITextField *yourTextField = [[UITextField alloc] init];
UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 5)];
leftView.backgroundColor = [UIColor clearColor];
yourTextField.leftViewMode = UITextFieldViewModeAlways;
yourTextField.leftView = leftView;

1
当您还需要使用图标的左视图时,此方法将无效
Reaper 2015年

@Reaper此方法也适用于图像。将所需的填充量添加到imageview框架的宽度,并将contentmode设置为center。imageView.contentMode = UIViewContentMode.Center imageView.frame = CGRectMake(0.0, 0.0, imageView.image!.size.width + 16.0, imageView.image!.size.height)
安迪

这太hacky了。已经有一个textRectForBounds方法来设置插图
Gerald

12

迅速

    // adjust place holder text
    let paddingView = UIView(frame: CGRectMake(0, 0, 10, usernameOrEmailField.frame.height))
    usernameOrEmailField.leftView = paddingView
    usernameOrEmailField.leftViewMode = UITextFieldViewMode.Always

1
这是一个非常便宜且容易的解决方法。谢谢!
shnaz

11

向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

好答案。提供失踪的财产:-)
帕特曼2015年

6

Swift 3 /在界面生成器中可设计/水平和垂直昆虫分开/可用的开箱即用

@IBDesignable
class TextFieldWithPadding: UITextField {

@IBInspectable var horizontalInset: CGFloat = 0
@IBInspectable var verticalInset: CGFloat = 0

override func textRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: horizontalInset, dy: verticalInset)
}

override func editingRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: horizontalInset , dy: verticalInset)
}

override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: horizontalInset, dy: verticalInset)
}
}

用法:

用法

在此处输入图片说明


5

我是在IB中完成的,在IB中,我在textView后面创建了一个UIView,该UIView稍长一些。将textField的背景色设置为清除。 在此处输入图片说明


5

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

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

4

这是用Swift 3编写的相同的子类UITextField。它与以前的Swift版本有很大的不同,您将看到:

import UIKit

class MyTextField: UITextField
    {
    let inset: CGFloat = 10

    // placeholder position
    override func textRect(forBounds bounds: CGRect) -> CGRect
        {
        return bounds.insetBy(dx: inset, dy: inset)
        }

    // text position
    override func editingRect(forBounds bounds: CGRect) -> CGRect
        {
        return bounds.insetBy(dx: inset, dy: inset)
        }

    override func placeholderRect(forBounds bounds: CGRect) -> CGRect
        {
        return bounds.insetBy(dx: inset, dy: inset)
        }
    }

顺便说一句,如果只想控制一侧的插入,也可以执行以下操作。如果将图像放置在UITextField的顶部,但希望用户在文本字段中看到它,则仅调整左插图的特定示例会派上用场:

    override func editingRect(forBounds bounds: CGRect) -> CGRect
        {
        return CGRect.init(x: bounds.origin.x + inset, y: bounds.origin.y, width: bounds.width - inset, height: bounds.height)
        }

4

Swift 4.2版本:

import UIKit

class InsetTextField: UITextField {

  let inset: CGFloat = 10

  override func textRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: inset, dy: inset)
  }


  override func editingRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: inset, dy: inset)
  }

  override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: inset, dy: inset)
  }

}

奇怪的是,当文本溢出可见矩形时,这会影响滚动性能(至少在iOS 12上)。插入值为15时,它甚至停止滚动。
Ixx

3

您可以通过使文本成为方法的子类UITextField并覆盖该-textRectForBounds:方法来调整文本在文本字段中的位置。


3

UITextField正如@Adam Waite指出的那样,您必须继承子类,这很荒谬,因为已经实现了这些方法。这是一个公开工厂方法的快速扩展,在我们的类别repo中也可用:

private class InsetTextField: UITextField {
    var insets: UIEdgeInsets

    init(insets: UIEdgeInsets) {
        self.insets = insets
        super.init(frame: CGRectZero)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("not intended for use from a NIB")
    }

    // placeholder position
    override func textRectForBounds(bounds: CGRect) -> CGRect {
        return super.textRectForBounds(UIEdgeInsetsInsetRect(bounds, insets))
    }

    // text position
    override func editingRectForBounds(bounds: CGRect) -> CGRect {
        return super.editingRectForBounds(UIEdgeInsetsInsetRect(bounds, insets))
    }
}

extension UITextField {

    class func textFieldWithInsets(insets: UIEdgeInsets) -> UITextField {
        return InsetTextField(insets: insets)
    }

}

您的答案中的链接已消失,您能否对其进行更新?
WendiKidd 2015年

修复了网址@WendiKidd
Christopher Pickslay

2

我添加了UITextField来处理该问题,该问题支持左,上,右和下插入以及清除按钮位置。

MRDInsetTextField.h

#import <UIKit/UIKit.h>

@interface MRDInsetTextField : UITextField

@property (nonatomic, assign) CGRect inset;

@end

MRDInsetTextField.m

#import "MRDInsetTextField.h"

@implementation MRDInsetTextField

- (id)init
{
    self = [super init];
    if (self) {
        _inset = CGRectZero;
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        _inset = CGRectZero;
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        _inset = CGRectZero;
    }
    return self;
}

- (void)setInset:(CGRect)inset {
    _inset = inset;

    [self setNeedsLayout];
}

- (CGRect)getRectForBounds:(CGRect)bounds withInset:(CGRect)inset {

    CGRect newRect = CGRectMake(
                         bounds.origin.x + inset.origin.x,
                         bounds.origin.y + inset.origin.y,
                         bounds.origin.x + bounds.size.width - inset.origin.x - inset.size.width,
                         bounds.origin.y + bounds.size.height - inset.origin.y - inset.size.height
                         );

    return newRect;
}

- (CGRect)textRectForBounds:(CGRect)bounds {
    return [self getRectForBounds:[super textRectForBounds:bounds] withInset:_inset];
}

- (CGRect)placeholderRectForBounds:(CGRect)bounds {
    return [self getRectForBounds:bounds withInset:_inset];
}

- (CGRect)editingRectForBounds:(CGRect)bounds {
    return [self getRectForBounds:[super editingRectForBounds:bounds] withInset:_inset];
}

- (CGRect)clearButtonRectForBounds:(CGRect)bounds {
    return CGRectOffset([super clearButtonRectForBounds:bounds], -_inset.size.width, _inset.origin.y/2 - _inset.size.height/2);
}

@end

* _someTextField *来自带有MRDInsetTextField自定义类的笔尖/故事板视图的用法示例

[(MRDInsetTextField*)_someTextField setInset:CGRectMake(5, 0, 5, 0)]; // left, top, right, bottom inset

谢谢。不过,对您的代码提出了一个建议-为什么将CGRect用于插入而不是UIEdgeInsets?
2014年

2

这没有其他示例那么短,但是采用了完全不同的方法来解决此问题。请注意,插入记号仍将开始与左边缘齐平,但是在键入/显示时,文本将正确缩进。如果您只是在寻找左边距并且您已经在使用它,则无需子类化即可工作UITextFieldDelegate文本字段,。您需要同时设置默认文本属性和键入属性。创建文本字段时,可以设置默认的文本属性。您需要在委托中设置的键入属性。如果您还使用占位符,则需要将其设置为相同的边距。综上所述,您会得到这样的结果。

首先在UITextField课程上创建一个类别。

//  UITextField+TextAttributes.h

#import <UIKit/UIKit.h>

@interface UITextField (TextAttributes)

- (void)setIndent:(CGFloat)indent;

@end


//  UITextField+TextAttributes.m
#import "UITextField+TextAttributes.h"

@implementation UITextField (TextAttributes)

- (void)setTextAttributes:(NSDictionary*)textAttributes indent:(CGFloat)indent
{
    if (!textAttributes) return;

    NSMutableParagraphStyle *paragraphStyle = [textAttributes objectForKey:NSParagraphStyleAttributeName];
    paragraphStyle.firstLineHeadIndent = indent;
    paragraphStyle.headIndent = indent;
}

- (void)setIndent:(CGFloat)indent
{
   [self setTextAttributes:self.defaultTextAttributes indent:indent];
   [self setTextAttributes:self.typingAttributes indent:indent];
}

@end

然后,如果您使用的是占位符,请确保使用设置相同缩进的属性占位符。创建具有适当属性的默认属性字典,如下所示:

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.firstLineHeadIndent = 7;
paragraphStyle.headIndent = 7;
NSDictionary *placeholderAttributes = [NSDictionary dictionaryWithObjectsAndKeys: paragraphStyle, NSParagraphStyleAttributeName, nil];

然后,导入以上类别,每当您创建文本字段时,都设置默认缩进,委托并使用上面定义的默认占位符属性。例如:

UITextField *textField = [[UITextField alloc] init];
textField.indent = 7;
textField.delegate = self;
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"Placeholder Text" attributes:placeholderAttributes];

最后,在委托中实现该textFieldDidBeginEditing方法,如下所示:

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    textField.indent = 7;
}

defaultTextAttributes包含的假设NSMutableParagraphStyle非常危险。我宁愿mutableCopy所有这些。
Ben Sinclair

1

我通常尝试避免子类化,但是如果您已经这样做,则可以这样做:

// add a property 
@property (nonatomic) UIEdgeInsets edgeInsets;

// and override:

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

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

避免子类化的任何原因?这一个有效的设计范例。
Stunner

1

抛出不需要子类化的另一个解决方案:

UITextField *txtField = [UITextField new];
txtField.borderStyle = UITextBorderStyleRoundedRect;

// grab BG layer
CALayer *bgLayer = txtField.layer.sublayers.lastObject;
bgLayer.opacity = 0.f;

// add new bg view
UIView *bgView = [UIView new];
bgView.backgroundColor = [UIColor whiteColor];
bgView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
bgView.userInteractionEnabled = NO;

[txtField addSubview: bgView];
[txtField sendSubviewToBack: bgView];

原始的UITextField 固定的UITextField

经过iOS 7和iOS 8测试。苹果仍然可能会修改UITextField的图层层次结构,从而使事情严重恶化。


1

这是一个全面的Swift答案,其中包括leftView(自定义图标)和自定义清除按钮,两者均在Interface Builder中设置,并带有可自定义的插图。

import UIKit

@IBDesignable
class InsetTextField: UITextField {
@IBInspectable var leftInset:CGFloat = 0
@IBInspectable var rightInset:CGFloat = 0
@IBInspectable var icon:UIImage? { didSet {
    let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 16, height: 16))
    imageView.image = icon
    self.leftView = imageView
    self.leftViewMode = .Always
} }

@IBInspectable var clearButton:UIImage? { didSet {
    let button = UIButton(type: .Custom)
    button.setImage(clearButton, forState: .Normal)
    button.addTarget(self, action: "clear", forControlEvents: UIControlEvents.TouchUpInside)
    button.frame = CGRect(x: 0, y: 0, width: 18, height: 18)
    self.rightView = button
    self.rightViewMode = .WhileEditing
} }

func clear() {
    self.text = ""
}

override func leftViewRectForBounds(bounds: CGRect) -> CGRect {
    var height:CGFloat = 0
    var width:CGFloat = 0
    if let leftView = self.leftView {
        height = leftView.bounds.height
        width = leftView.bounds.width
    }

    return CGRect(x: leftInset, y: bounds.height/2 - height/2, width: width, height: height)
}

override func rightViewRectForBounds(bounds: CGRect) -> CGRect {
    var height:CGFloat = 0
    var width:CGFloat = 0
    if let rightView = self.rightView {
        height = rightView.bounds.height
        width = rightView.bounds.width
    }

    return CGRect(x: bounds.width - width - rightInset, y: bounds.height/2 - height/2, width: width, height: height)
}

}

1

实际适用并涵盖所有情况的解决方案:

  • offsetBy不宜使用insetBy
  • 还应该调用super函数来获取原始函数Rect
  • 边界错误。您需要偏移原始的X,Y。边界的X,Y为零。
  • 例如,当设置UITextField的leftView时,原始的x,y可以为非零。

样品:

override func textRect(forBounds bounds: CGRect) -> CGRect {
    return super.textRect(forBounds: bounds).offsetBy(dx: 0.0, dy: 4)
}


override func editingRect(forBounds bounds: CGRect) -> CGRect {
    return super.editingRect(forBounds: bounds).offsetBy(dx: 0.0, dy: 4)
}

0

如果只想更改TOP和LEFT缩进,则

//占位符位置

- (CGRect)textRectForBounds:(CGRect)bounds {

CGRect frame = bounds;
frame.origin.y = 3;
 frame.origin.x = 5;
bounds = frame;
return CGRectInset( bounds , 0 , 0 );
}

//文字位置

- (CGRect)editingRectForBounds:(CGRect)bounds {

CGRect frame = bounds;
frame.origin.y = 3;
 frame.origin.x = 5;
bounds = frame;
return CGRectInset( bounds , 0 , 0 );
}

-1

无需子类也可检查的快速解决方案

extension UITextField {
    @IBInspectable var textInsets: CGPoint {
            get {
                return CGPoint.zero
            }
            set {
                layer.sublayerTransform = CATransform3DMakeTranslation(newValue.x, newValue.y, 0);
            }
        }
}
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.