UITextField的文本插入?

问题描述 投票:386回答:27

我想插入一个qazxsw poi的文本。

这可能吗?

ios cocoa-touch uitextfield
27个回答
600
投票

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

-editingRectForBounds:

12
投票

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

像这样:

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

11
投票

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

OSTextField.h

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;

OSTextField.m

#import <UIKit/UIKit.h>

@interface OSTextField : UITextField

@property (nonatomic, assign) UIEdgeInsets edgeInsets;

@end

11
投票

迅速

#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

10
投票

迅速

 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)
    }
}

6
投票

Swift 3 /可在界面构建器中设计/分离水平和垂直昆虫/开箱即用

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

用法:

@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) } }

&

usage


5
投票

这是我在没有做任何子类的情况下发现的最快的方法:

enter image description here

在Swift中:

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

4
投票

这是用Swift 3编写的相同的子类UITextField。它与Swift的早期版本完全不同,你会看到:

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

顺便提一下,如果你想控制一侧的插图,你也可以做类似下面的事情。如果您将图像放在UITextField的顶部,但是您希望它对用户显示在文本字段中,则仅调整左侧插入的这个特定示例会派上用场:

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)
        }
    }

3
投票

您可以通过使文本字段成为 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) } 的子类并覆盖UITextField方法来调整文本字段中文本的位置。


3
投票

你必须继承这是荒谬的,因为-textRectForBounds:已经实现了这些方法,正如@Adam Waite指出的那样。这是一个快速扩展,公开了一个工厂方法,也可以在我们的UITextField中找到:

categories repo

3
投票

Swift 4.2版本:

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)
    }

}

289
投票

我能够通过以下方式完成:

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

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

当然记得导入QuartzCore并将Framework添加到您的项目中。


2
投票

我将UITextField细分为处理它,支持left,top,right和bottom inset,以及清除按钮定位。

MRDInsetTextField.h

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)
  }

}

MRDInsetTextField.m

#import <UIKit/UIKit.h>

@interface MRDInsetTextField : UITextField

@property (nonatomic, assign) CGRect inset;

@end

使用示例* _someTextField *来自nib / storyboard视图,带有MRDInsetTextField自定义类

#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

2
投票

这并不像其他示例那么短,但采用完全不同的方法来解决这个问题。请注意,插入符号仍将从左边缘开始刷新,但在键入/显示时文本将正确缩进。如果您只查找左边距并且您已经在文本字段中使用[(MRDInsetTextField*)_someTextField setInset:CGRectMake(5, 0, 5, 0)]; // left, top, right, bottom inset ,则无需子类化即可。您需要设置默认文本属性和输入属性。您在创建文本字段时设置默认文本属性。您需要在委托中设置的输入属性。如果您还使用占位符,则还需要将其设置为相同的边距。总而言之,你会得到这样的东西。

首先在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

2
投票

我在IB中做到了这一点,我在textView后面创建了一个更长一点的UIView。将textField背景颜色设置为clear。 - (void)textFieldDidBeginEditing:(UITextField *)textField { textField.indent = 7; }


1
投票

我通常会尝试避免使用子类,但是如果你已经这样做了

enter image description here

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)];
}

测试iOS 7和iOS 8.两者都在工作。 Apple可能仍有机会修改UITextField的层次结构,从而严重搞乱事情。


1
投票

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

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];

0
投票

如果你想只改变TOP和LEFT缩进

//占位符位置

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)
}

}

//文字位置

- (CGRect)textRectForBounds:(CGRect)bounds {

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

0
投票

没有子类的快速解决方案也可以检查

- (CGRect)editingRectForBounds:(CGRect)bounds {

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

165
投票

在从UITextField派生的类中,至少覆盖以下两个方法:

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

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

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

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


158
投票

如果您只需要左边距,可以试试这个:

return CGRectInset(bounds , 10, 10);

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


88
投票

怎么样的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; @IBInspectable快速类。

@IBDesignable

你会在故事板中看到这一点。

更新 - 斯威夫特3

@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)
    }
}

27
投票

如果您有一个清除按钮,则接受的答案对您不起作用。我们也应该通过致电@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) } } 来防范苹果未来的变化。

因此,为了确保文本不与clear按钮重叠,让我们首先从super获取'default'值,然后根据需要进行调整。

此代码将在文本字段的顶部,左侧和底部添加10px插入内容:

super

注意:UIEdgeInsetsMake按顺序获取参数:top,left,bottom,right。


17
投票

以为我会提供一个Swift解决方案

@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

14
投票

使用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) } } 是正确的方法。我把它包装在我的子类中,所以你可以简单地使用textRectForBounds:。见textEdgeInsets


12
投票

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

SSTextField中加入UITextField。为了模拟文本字段周围的插图,我保持10 px左边,宽度比视图小20 px。对于文本字段周围的圆角边框,请使用视图的边框

UIView
© www.soinside.com 2019 - 2024. All rights reserved.