it-swarm.com.de

Texteinschub für UITextField?

Ich möchte das text einer UITextField einfügen. 

Ist das möglich?

377
RunLoop

Durch das Überschreiben von -textRectForBounds: wird nur die Einfügung des Platzhaltertextes geändert. Um die Einfügung des bearbeitbaren Textes zu ändern, müssen Sie auch -editingRectForBounds: überschreiben.

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

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

Ich konnte es durch:

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

Denken Sie natürlich auch daran, QuartzCore zu importieren und das Framework zu Ihrem Projekt hinzuzufügen.

287
chuthan20

Überschreiben Sie in einer von UITextField abgeleiteten Klasse mindestens diese beiden Methoden:

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

Es könnte so einfach sein, wenn Sie keinen zusätzlichen Inhalt haben:

return CGRectInset(bounds , 10, 10);

UITextField bietet verschiedene Positionierungsmethoden, die Sie überschreiben können.

164
drawnonward

Wenn Sie nur einen linken Rand benötigen, können Sie Folgendes versuchen:

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;

Für mich geht das. Ich hoffe das kann helfen.

155
roberto.buratti

Wie wäre es mit einer Swift-Klasse @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)
    }
}

Sie werden dies in Ihrem Storyboard sehen.

enter image description here

Update - 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)
    }
}
87
mash

Wenn Sie einen klaren Button haben, funktioniert die akzeptierte Antwort nicht für Sie. Wir sollten uns auch vor zukünftigen Änderungen durch Apple schützen, indem wir super aufrufen.

Um sicherzustellen, dass der Text die Schaltfläche "Löschen" nicht überlappt, erhalten Sie zunächst den Wert "default" von super und passen Sie ihn gegebenenfalls an.

Dieser Code fügt am oberen, linken und unteren Rand des Textfelds 10px-Einfügungen hinzu:

@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

Anmerkung: UIEdgeInsetsMake verwendet Parameter in der Reihenfolge: top , left , bottom , right .

27
Chris Nolet

Ich dachte, ich würde eine schnelle Lösung liefern

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

Die Verwendung von textRectForBounds: ist der richtige Ansatz. Ich habe dies in meine Unterklasse eingepackt, sodass Sie einfach textEdgeInsets verwenden können. Siehe SSTextField .

14
Sam Soffes

Ein guter Ansatz, um UITextField mit Füllzeichen zu versehen, ist das Unterklassen von UITextField und das Hinzufügen einer edgeInsets-Eigenschaft. Sie legen dann die edgeInsets fest und das UITextField wird entsprechend gezeichnet. Dies funktioniert auch mit einem benutzerdefinierten LeftView- oder RightView-Set.

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
11
Brody Robertson

Sie können den Text-Inset für UITextField festlegen, indem Sie die leftView festlegen. 

So was: 

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;
11
Golden

Für Menschen, die eine einfachere Lösung suchen. 

Fügen Sie die UITextField innerhalb einer UIView hinzu. Um ein Textfeld zu simulieren, halte ich 10 Pixel links und die Breite ist 20 Pixel weniger als die Ansicht. Verwenden Sie für einen abgerundeten Eckenrand um das Textfeld den Rand der Ansicht 

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

Swift

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

Swift 3 Version für Xcode 8.3.1 ab Mai 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)
    }
}
6
lcl

Swift 3/Designable in Interface Builder/Separate horizontale und vertikale Insekten/sofort einsetzbar

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

verwendungszweck:

 usage

&

 enter image description here

6
zgorawski

Hier ist dasselbe untergeordnete UITextField in Swift 3 geschrieben. Es unterscheidet sich deutlich von früheren Swift-Versionen, wie Sie sehen werden:

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

Übrigens können Sie auch etwas wie das Folgende tun, wenn Sie den Einschub nur einer Seite steuern möchten. Dieses spezielle Beispiel, nur den linken Einschub anzupassen, ist hilfreich, wenn Sie ein Bild auf das UITextField-Objekt setzen, es jedoch für den Benutzer als Textfeld erscheinen soll:

    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
Gene Loparco

Es ist absurd, dass Sie eine Unterklasse bilden müssen, da UITextField die Methoden bereits implementiert, wie @Adam Waite zeigt. Hier ist eine Swift-Erweiterung, die eine Factory-Methode verfügbar macht, auch in unserem categories-Repo verfügbar:

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

}

Sie können die Positionierung des Textes in einem Textfeld anpassen, indem Sie eine Unterklasse von UITextField erstellen und die -textRectForBounds:-Methode überschreiben.

3

Es ist der schnellste Weg, den ich ohne Unterklassen gefunden habe:

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

In Swift:

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

Dies ist nicht so kurz wie bei den anderen Beispielen, es wird jedoch ein völlig anderer Ansatz gewählt, um dieses Problem zu lösen. Beachten Sie, dass die Einfügemarke immer noch auf den linken Rand ausgerichtet wird, der Text jedoch richtig eingerückt wird, wenn er eingegeben/angezeigt wird. Dies funktioniert ohne Unterklassifizierung, wenn Sie nur nach einem linken Rand suchen und bereits UITextFieldDelegate für Ihre Textfelder verwenden. Sie müssen sowohl die Standardtextattribute als auch die Typattribute festlegen. Sie legen die Standardtextattribute fest, wenn Sie das Textfeld erstellen. Die Typattribute, die Sie im Delegaten festlegen müssen. Wenn Sie auch einen Platzhalter verwenden, sollten Sie diesen auch auf den gleichen Rand setzen. Wenn man es zusammenstellt, bekommt man so etwas.

Erstellen Sie zuerst eine Kategorie in der UITextField-Klasse. 

//  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

Wenn Sie platzierte Inhaber verwenden, stellen Sie sicher, dass ein zugeordneter Platzhalter den gleichen Einzug setzt. Erstellen Sie ein Standardattributwörterbuch mit den richtigen Attributen, etwa wie folgt:

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

Importieren Sie dann die oben genannte Kategorie. Wenn Sie ein Textfeld erstellen, legen Sie den Standardeinzug fest, den Delegaten und verwenden die oben definierten Standardplatzhalterattribute. Zum Beispiel:

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

Implementieren Sie schließlich im Delegaten die textFieldDidBeginEditing-Methode, etwa wie folgt:

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

Ich habe UITextField subclased, um dieses Problem zu lösen, das den linken, oberen, rechten und unteren Einschub sowie das Löschen von Tasten unterstützt.

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

Verwendungsbeispiel, bei dem * _someTextField * aus der Ansicht "Feder"/"Storyboard" mit der Klasse " MRDInsetTextField custom" stammt

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

Ich habe dies in IB gemacht, wo ich ein UIView hinter der Textansicht erstellt habe, das etwas länger war. Wenn die Hintergrundfarbe von textField auf clear ..__ gesetzt ist.  enter image description here

2
jeremy wilson

So werfen Sie eine andere Lösung ein, die keine Unterklassen erfordert:

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

Getestet mit iOS 7 und iOS 8. Beide funktionieren. Möglicherweise besteht jedoch die Möglichkeit, dass Apple die Ebenenhierarchie von UITextField verändert, was die Dinge sehr vermasselt.

1
Lukas

Hier ist eine umfassende schnelle Antwort, die ein leftView-Symbol (benutzerdefiniertes Symbol) und eine benutzerdefinierte Schaltfläche zum Löschen enthält, die beide im Interface Builder mit anpassbaren Insets festgelegt werden.

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
rmooney

Normalerweise versuche ich, Unterklassen zu vermeiden, aber das funktioniert, wenn Sie bereits

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

Wenn Sie nur den Einzug von TOP und LEFT ändern möchten, dann 

// Platzhalterposition

- (CGRect)textRectForBounds:(CGRect)bounds {

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

// Textposition

- (CGRect)editingRectForBounds:(CGRect)bounds {

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

Swift 4.2 Version:

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

}
0
Bruno Paulino

Schnelle Lösung ohne Unterklasse und auch inspizierbar

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