Texto insertado para UITextField?

Me gustaría insertar el texto de un UITextField .

es posible?

Anulación de -textRectForBounds: solo cambiará el recuadro del texto del marcador de posición. Para cambiar el recuadro del texto editable, también debe sobrescribir -editingRectForBounds:

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

Pude hacerlo a través de:

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

Por supuesto, recuerde importar QuartzCore y también agregue el Marco a su proyecto.

En una clase derivada de UITextField, anule al menos estos dos métodos:

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

Puede ser tan simple como esto si no tienes contenido adicional:

 return CGRectInset(bounds , 10, 10); 

UITextField proporciona varios métodos de posicionamiento que puede anular.

Si necesita solo un margen izquierdo, puede intentar esto:

 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; 

Esto funciona para mi. Espero que esto pueda ayudar.

¿ @IBInspectable @IBDesignable una clase rápida @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) } } 

Verás esto en tu guión gráfico.

enter image description here

Actualización – 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) } } 

Si tiene un botón claro, la respuesta aceptada no funcionará para usted. También deberíamos evitar que Apple cambie las cosas en el futuro llamando a super .

Por lo tanto, para asegurarnos de que el texto no se superpone al botón borrar, obtengamos el valor ‘predeterminado’ de super primero, luego ajuste según sea necesario.

Este código agregará una inserción de 10px en la parte superior, izquierda e inferior del campo de texto:

 @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 

Nota: UIEdgeInsetsMake toma los parámetros en el orden: arriba , izquierda , abajo , derecha .

Pensé que podría suministrar una solución Swift

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

Usar textRectForBounds: es el enfoque correcto. He envuelto esto en mi subclase para que pueda usar textEdgeInsets . Ver SSTextField .

Un buen enfoque para agregar relleno a UITextField es la subclase UITextField y agregar una propiedad edgeInsets. Luego configura los edgeInsets y el UITextField se dibujará en consecuencia. Esto también funcionará correctamente con un conjunto personalizado leftView o rightView.

OSTextField.h

 #import  @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 

Puede configurar el recuadro de texto para UITextField configurando leftView.

Me gusta esto:

 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; 

Para las personas que buscan una solución más fácil.

Agregue el UITextField dentro de una UIView . Para simular un recuadro alrededor del campo de texto, mantengo 10 px a la izquierda y el ancho es 20px menor que la vista. Para un borde de esquina redondeada alrededor del campo de texto, use el borde de la vista

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

Rápido

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

Versión de Swift 3 para Xcode 8.3.1 a partir de mayo de 2017:

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

Swift 3 / Designable en Interface Builder / Insectos separados horizontales y verticales / utilizable fuera de la caja

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

uso:

uso

&

enter image description here

Aquí está el mismo UITextField subclasificado escrito en Swift 3. Es bastante diferente de las versiones anteriores de Swift, como verá:

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

Por cierto, también puedes hacer algo como lo siguiente, si quieres controlar el recuadro de un solo lado. Este ejemplo particular de ajustar solo el recuadro izquierdo es útil si coloca una imagen encima del UITextField pero desea que el usuario vea que se encuentra dentro del campo de texto:

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

Puede ajustar el posicionamiento del texto dentro de un campo de texto haciéndolo una subclase de UITextField y anulando el método -textRectForBounds: .

Es absurdo que tengas que subclase, ya que UITextField ya implementa los métodos, como señala @Adam Waite. Aquí hay una extensión rápida que expone un método de fábrica, también disponible en nuestro repository de categorías :

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

Es la forma más rápida que he encontrado sin hacer ninguna subclases:

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

En Swift:

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

Subcribí UITextField para manejar esto que admite el recuadro izquierdo, superior, derecho e inferior, y también el posicionamiento claro del botón.

MRDInsetTextField.h

 #import  @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 

Ejemplo de uso en el que * _someTextField * proviene de la vista de plumilla / guion gráfico con la clase MRDInsetTextField personalizada

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

Hice esto en IB donde creé un UIView Behind the textView que fue un poco más largo. Con el color de fondo textField configurado para borrar. enter image description here

Normalmente bash evitar las subclases, pero esto funciona si ya lo has hecho:

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

Para lanzar otra solución que no necesita subclasificación:

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

Original UITextFieldFixed UITextField

Probado con iOS 7 e iOS 8. Ambos funcionan. Todavía podría existir la posibilidad de que Apple modifique la jerarquía de capas de UITextField arruinando las cosas mal.

Esto no es tan corto como los otros ejemplos, pero toma un enfoque completamente diferente para resolver este problema. Tenga en cuenta que el símbolo de intercalación aún comenzará a nivelarse con el borde izquierdo, pero el texto se sangrará adecuadamente cuando se escriba / muestre. Esto funciona sin UITextFieldDelegate subclases si solo busca un margen izquierdo y ya está utilizando UITextFieldDelegate para sus campos de texto. Debe establecer los atributos de texto predeterminados y los atributos de escritura. Establece los atributos de texto predeterminados cuando crea el campo de texto. Los atributos de tipeo que necesita establecer en el delegado. Si también está usando un marcador de posición, también querrá establecerlo en el mismo margen. Poniéndolo en conjunto, obtienes algo como esto.

Primero crea una categoría en la clase UITextField .

 // UITextField+TextAttributes.h #import  @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 

Luego, si usa los titulares colocados, asegúrese de usar un marcador de posición atribuido con la misma sangría. Cree un diccionario atribuido por defecto con los atributos adecuados, algo como esto:

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

Luego, importe la categoría anterior y cada vez que cree un campo de texto, establezca la sangría predeterminada, el delegado y use los atributos predeterminados de marcador de posición definidos anteriormente. Por ejemplo:

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

Por último, en el delegado, implemente el método textFieldDidBeginEditing , algo como esto:

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

Aquí hay una respuesta completa de Swift que incluye un leftView (icono personalizado) y un botón de borrar personalizado, ambos configurados en Interface Builder con inserciones personalizables.

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

Solución rápida sin subclase y también inspectable

 extension UITextField { @IBInspectable var textInsets: CGPoint { get { return CGPoint.zero } set { layer.sublayerTransform = CATransform3DMakeTranslation(newValue.x, newValue.y, 0); } } } 

Si quieres cambiar la sangría SUPERIOR e IZQUIERDA solo entonces

// posición de marcador de posición

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

// posición del texto

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