UITextfield leftView / rightView-Auffüllung unter iOS7


93

Die Ansichten leftView und rightView eines UITextField unter iOS7 befinden sich sehr nahe am Textfeldrand.

Wie kann ich diesen Elementen eine (horizontale) Polsterung hinzufügen?

Ich habe versucht, den Rahmen zu ändern, aber es hat nicht funktioniert

uint padding = 10;//padding for iOS7
UIImageView * iconImageView = [[UIImageView alloc] initWithImage:iconImage];    
iconImageView.frame = CGRectMake(0 + padding, 0, 16, 16);
textField.leftView = iconImageView;

Bitte beachten Sie, dass ich nicht daran interessiert bin, dem Text des Textfelds eine Auffüllung hinzuzufügen, wie z. B. Auffüllen für UITextField mit UITextBorderStyleNone festlegen


Mögliches Duplikat des Texteinsatzes für UITextField?
Zorayr

1
Nein, hier geht es darum, das Bild, das als linke Ansicht in einem Textfeld angezeigt wird, einzurücken. Den Text selbst nicht einrücken. Probieren Sie seinen Code aus und Sie werden sehen, dass durch die Einstellung von leftView auf ein Bild dieses Bild ohne Auffüllen am linken Rand des Textfelds platziert wird. Es sieht hässlich aus.
Stein

Antworten:


90

Ich habe gerade selbst daran gearbeitet und diese Lösung verwendet:

- (CGRect) rightViewRectForBounds:(CGRect)bounds {

    CGRect textRect = [super rightViewRectForBounds:bounds];
    textRect.origin.x -= 10;
    return textRect;
}

Dadurch wird das Bild um 10 von rechts verschoben, anstatt dass das Bild in iOS 7 gegen den Rand gedrückt wird.

Darüber hinaus gehörte dies zu einer Unterklasse von UITextField, die erstellt werden kann durch:

  1. Erstellen Sie eine neue Datei, die eine Unterklasse UITextFieldanstelle der Standarddatei istNSObject
  2. Fügen Sie eine neue Methode mit dem Namen hinzu - (id)initWithCoder:(NSCoder*)coder, um das Bild festzulegen

    - (id)initWithCoder:(NSCoder*)coder {
        self = [super initWithCoder:coder];
    
        if (self) {
    
            self.clipsToBounds = YES;
            [self setRightViewMode:UITextFieldViewModeUnlessEditing];
    
            self.leftView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"textfield_edit_icon.png"]];
        }
    
        return self;
    }
    
  3. Möglicherweise müssen Sie importieren #import <QuartzCore/QuartzCore.h>

  4. Fügen Sie die rightViewRectForBoundsobige Methode hinzu

  5. Klicken Sie im Interface Builder auf das TextField, das Sie unterklassifizieren möchten, und ändern Sie das Klassenattribut in den Namen dieser neuen Unterklasse


Wie verwende ich IBDesignable dafür?
Riddhi

167

Eine viel einfachere Lösung, die Folgendes nutzt contentMode:

    arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"down_arrow"]];
    arrow.frame = CGRectMake(0.0, 0.0, arrow.image.size.width+10.0, arrow.image.size.height);
    arrow.contentMode = UIViewContentModeCenter;

    textField.rightView = arrow;
    textField.rightViewMode = UITextFieldViewModeAlways;

In Swift 3

    let arrow = UIImageView(image: UIImage(named: "arrowDrop"))
    if let size = arrow.image?.size {
        arrow.frame = CGRect(x: 0.0, y: 0.0, width: size.width + 10.0, height: size.height)
    }
    arrow.contentMode = UIViewContentMode.center
    self.textField.rightView = arrow
    self.textField.rightViewMode = UITextFieldViewMode.always

1
Sie können auch ScaleAspectFit anstelle von Mitte verwenden, wenn die Bildgröße nicht mit dem genauen Rahmen übereinstimmt.
Mihir Mehta

Ich habe Ihr Beispiel für UIButton (anstelle von UIImageView) verwendet, während der Typ InfoLight ist.
OhadM

Ich habe festgestellt, dass ".right" anstelle von ".center" eher wie eine integrierte Suchleiste aussieht, wie die in der Kontakte-App. Tolle Lösung dafür, danke, dass du es gepostet hast.
James Toomey

Oder wenn Sie bei der Neuerstellung des Designs präzise sein müssen, setzen Sie das Bild nach links und erhöhen Sie dann die Breite, um eine exakte Polsterung zu erzielen
jovanjovanovic

4
Dies scheint mit iOS 13 und Xcode 11 Beta 7 nicht mehr zu funktionieren. Funktioniert jedoch gut mit iOS 11/12.
PatrickDotStar

49

Am einfachsten ist es, eine UIView zu leftView / righView hinzuzufügen und eine ImageView zu UIView hinzuzufügen. Passen Sie den Ursprung von ImageView in UIView an einer beliebigen Stelle an. Dies hat bei mir wie ein Zauber funktioniert. Es werden nur wenige Codezeilen benötigt

UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 5, 26, 26)];
imgView.image = [UIImage imageNamed:@"img.png"];

UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
[paddingView addSubview:imgView];
[txtField setLeftViewMode:UITextFieldViewModeAlways];
[txtField setLeftView:paddingView];

UIViewContentMode funktioniert nicht, aber diese Antwort funktioniert wie ein Zauber!
Nigong

14

Dies funktioniert hervorragend für Swift:

let imageView = UIImageView(image: UIImage(named: "image.png"))
imageView.contentMode = UIViewContentMode.Center
imageView.frame = CGRectMake(0.0, 0.0, imageView.image!.size.width + 20.0, imageView.image!.size.height)
textField.rightViewMode = UITextFieldViewMode.Always
textField.rightView = imageView

Wert vom Typ 'Zeichenfolge' kann nicht in den erwarteten Argumenttyp 'UIImage konvertiert werden? "

7

Das funktioniert bei mir

UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 20)];
self.passwordTF.leftView = paddingView;
self.passwordTF.leftViewMode = UITextFieldViewModeAlways;

Möge es dir helfen.


6

Ich mag diese Lösung, weil sie das Problem mit einer einzigen Codezeile löst

myTextField.layer.sublayerTransform = CATransform3DMakeTranslation(10.0f, 0.0f, 0.0f);

Hinweis: .. oder 2, wenn Sie QuartzCore als Zeile einfügen möchten :)


1
Dies bewegt auch die Grenze
Softlion

1
aber löst nicht das Problem mit der rechten Polsterung nur das linke Polsterungsproblem
carmen_munich

1
Ich hatte ein besseres Ergebnis mit rightView.layer.sublayerTransform = CATransform3DMakeTranslation (-10.0f, 0.0f, 0.0f), aber +1 für die Methode
Thibaud David

Beachten Sie, dass dadurch auch die Schaltfläche "Löschen" des Textfelds nach rechts verschoben wird, wodurch es über den Rand des Textfelds hinausgeschoben werden kann. Wenn Sie die Schaltfläche zum Löschen nicht benötigen, ist dies ein großartiger Ansatz, andernfalls möglicherweise nicht.
Tom Harrington

4

Der beste Weg, dies zu tun, besteht darin, einfach eine Klasse mit der Unterklasse von UITextField und in der .m-Datei zu erstellen

  #import "CustomTextField.h"
  #import <QuartzCore/QuartzCore.h>
  @implementation CustomTextField


- (id)initWithCoder:(NSCoder*)coder 
 {
self = [super initWithCoder:coder];

if (self) {

    //self.clipsToBounds = YES;
    //[self setRightViewMode:UITextFieldViewModeUnlessEditing];

    self.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,15,46)];
    self.leftViewMode=UITextFieldViewModeAlways;
      }

return self;

}

Gehen Sie dazu zu Ihrem Storyboard oder xib, klicken Sie auf Identitätsinspektor und ersetzen Sie UITextfield durch Ihre eigene Option "CustomTextField" in der Klasse.

Hinweis: Wenn Sie einfach ein Auffüllen mit automatischem Layout für das Textfeld angeben, wird Ihre Anwendung nicht ausgeführt und zeigt nur einen leeren Bildschirm an.


3

Ich habe das irgendwo gefunden ...

UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)];
paddingView.backgroundColor = [UIColor clearColor];
itemDescription.leftView = paddingView;
itemDescription.leftViewMode = UITextFieldViewModeAlways;

[self addSubview:itemDescription];

4
Das fügt dem Text nur eine Auffüllung hinzu, was der Fragesteller nicht sucht. Er will keine klare linke Sicht. Er möchte, dass ein Bild als linke Ansicht angezeigt wird.
Stein

Sie können das Bild einfach in die paddingView einfügen.
Matheus Weber

3

Anstatt imageView oder image zu manipulieren, können wir eine von Apple für rightView bereitgestellte Methode überschreiben.

class CustomTextField : UITextField { 

override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
    let offset = 5
    let width  = 20
    let height = width
    let x = Int(bounds.width) - width - offset
    let y = offset
    let rightViewBounds = CGRect(x: x, y: y, width: width, height: height)
    return rightViewBounds
}}

und auf die gleiche Weise können wir unter func für die linke Ansicht überschreiben.

override func leftViewRect(forBounds bounds: CGRect) -> CGRect {
    /*return as per requirement*/

}

3

Swift 5

class CustomTextField: UITextField {
    func invalidate() {
        let errorImage =  UIImageView(image: UIImage(named: "errorImage"))
        errorImage.frame = CGRect(x: 8, y: 8, width: 16, height: 16)
        rightView = UIView(frame: CGRect(x: 0, y: 0, width: 32, height: 32))
        rightView?.addSubview(errorImage)
        rightViewMode = .always
    }
}

Du wirst wollen:

  • Unterklasse UITextField
  • Schreiben Sie eine ungültige Methode in das untergeordnete Textfeld
  • Erstellen Sie bei der Methode zum Ungültigmachen ein UIView Bild , das größer als Ihr Bild ist
  • Platzieren Sie Ihr Bild in der Ansicht
  • Weisen Sie die Ansicht zu UITextField.rightView

2

Hier ist eine Lösung:

 UIView *paddingTxtfieldView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 42)]; // what ever you want 
 txtfield.leftView = paddingTxtfieldView;
 txtfield.leftViewMode = UITextFieldViewModeAlways;

1

Erstellen Sie eine benutzerdefinierte UITextField-Klasse und verwenden Sie diese Klasse anstelle von UITextField. Override - (CGRect) textRectForBounds: (CGRect) Grenzen, um das benötigte Rect festzulegen

Beispiel

- (CGRect)textRectForBounds:(CGRect)bounds{
     CGRect textRect = [super textRectForBounds:bounds];
     textRect.origin.x += 10;
     textRect.size.width -= 10;
     return textRect;
}

1

Das folgende Beispiel dient zum Hinzufügen eines horizontalen Auffüllens zu einer linken Ansicht, die zufällig ein Symbol ist. Sie können den ähnlichen Ansatz zum Hinzufügen eines Auffüllens zu einer beliebigen UIViewAnsicht verwenden, die Sie als linke Ansicht des Textfelds verwenden möchten.

Innerhalb der UITextFieldUnterklasse:

static CGFloat const kLeftViewHorizontalPadding = 10.0f;

@implementation TextFieldWithLeftIcon
{
  UIImage *_image;
  UIImageView *_imageView;
}

- (instancetype)initWithFrame:(CGRect)frame image:(UIImage *)image
{
  self = [super initWithFrame:frame];
  if (self) {
    if (image) {
      _image = image;
      _imageView = [[UIImageView alloc] initWithImage:image];
      _imageView.contentMode = UIViewContentModeCenter;
      self.leftViewMode = UITextFieldViewModeAlways;
      self.leftView = _imageView;
    }
  }
  return self;
}

#pragma mark - Layout 

- (CGRect)leftViewRectForBounds:(CGRect)bounds
{
  CGFloat widthWithPadding = _image.size.width + kLeftViewHorizontalPadding * 2.0f;
  return CGRectMake(0, 0, widthWithPadding, CGRectGetHeight(bounds));
}

Obwohl wir hier eine Unterklasse UITextFieldsind, glaube ich, dass dies der sauberste Ansatz ist.


1
- (CGRect)rightViewRectForBounds:(CGRect)bounds
{
    return CGRectMake(bounds.size.width - 40, 0, 40, bounds.size.height);
}

Wenn das UITextFieldin a eingebettet ist UISearchBar, wie weisen Sie das UISearchBaran, Ihre UITextFieldUnterklasse zu verwenden?
Crishoj

1

Vielen Dank für Ihre Antworten. Zu meiner Überraschung passte keiner von ihnen wirklich das richtige Ansichtsbild in mein Textfeld und lieferte dennoch die erforderliche Polsterung. Dann dachte ich daran, den AspectFill-Modus zu verwenden, und es geschahen Wunder. Für zukünftige Suchende habe ich Folgendes verwendet:

UIImageView *emailRightView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 35, 35)];
emailRightView.contentMode = UIViewContentModeScaleAspectFill;
emailRightView.image = [UIImage imageNamed:@"icon_email.png"];
emailTextfield.rightViewMode = UITextFieldViewModeAlways;
emailTextfield.rightView = emailRightView;

Die 35 im Rahmen meiner Bildansicht repräsentiert die Höhe meines E-Mail-Textfelds. Sie können es jederzeit an Ihre Bedürfnisse anpassen.


1

Ich habe dieses Problem selbst gehabt, und die bei weitem einfachste Lösung besteht darin, Ihr Bild so zu ändern, dass jeder Seite des Bildes einfach eine Auffüllung hinzugefügt wird!

Ich habe gerade mein PNG-Bild geändert, um 10 Pixel transparenten Abstand hinzuzufügen, und es funktioniert gut, ohne Codierung!


1

Wenn Sie eine UIImageView als leftView verwenden, müssen Sie diesen Code verwenden:

Achtung: Verwenden Sie nicht inside viewWillAppear oder viewDidAppear

-(UIView*)paddingViewWithImage:(UIImageView*)imageView andPadding:(float)padding
{
    float height = CGRectGetHeight(imageView.frame);
    float width =  CGRectGetWidth(imageView.frame) + padding;

    UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];

    [paddingView addSubview:imageView];

    return paddingView;
}

1

Ich habe in meiner ViewController-Klasse eine benutzerdefinierte Methode erstellt, wie unten gezeigt:

- (void) modifyTextField:(UITextField *)textField
{
    // Prepare the imageView with the required image
    uint padding = 10;//padding for iOS7
    UIImageView * iconImageView = [[UIImageView alloc] initWithImage:iconImage];    
    iconImageView.frame = CGRectMake(0 + padding, 0, 16, 16);

    // Set the imageView to the left of the given text field.
    textField.leftView = iconImageView;
    textField.leftViewMode = UITextFieldViewModeAlways;
}

Jetzt kann ich diese Methode in ( viewDidLoadMethode) aufrufen und eine meiner TextFieldsMethoden an diese Methode senden und sowohl rechts als auch links Auffüllungen hinzufügen sowie Text- und Hintergrundfarben angeben, indem ich nur eine Codezeile wie folgt schreibe:

[self modifyTextField:self.firstNameTxtFld];

Dies funktionierte perfekt unter iOS 7! Hoffe das funktioniert auch unter iOS 8 und 9 noch!

Ich weiß, dass das Hinzufügen zu vieler Ansichten das Laden eines etwas schwereren Objekts erschwert. Als ich mir jedoch Sorgen über die Schwierigkeiten bei anderen Lösungen machte, war ich voreingenommener gegenüber dieser Methode und flexibler bei der Verwendung dieser Methode. ;)

Hoffe, diese Antwort könnte hilfreich oder nützlich sein, um eine andere Lösung für jemand anderen zu finden.

Prost!


1

Das funktioniert bei mir genauso wie ich es suche:

func addImageViewInsideMyTextField() {
    let someView = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 24))
    let imageView = UIImageView(image: UIImage(named: "accountImage"))
    imageView.frame = CGRect(x: 16, y: 0, width: 24, height: 24)
    imageView.contentMode = .scaleAspectFit
    someView.addSubview(imageView)

    self.myTextField.leftView = someView
    self.myTextField.leftViewMode = .always
}

1

Seit iOS 13 und Xcode 11 ist dies die einzige Lösung, die für uns funktioniert.

// Init of custom UITextField
override init(frame: CGRect) {
    super.init(frame: frame)

    if let size = myButton.imageView?.image?.size {
        myButton.frame = CGRect(x:0, y: 0, width: size.width, height: size.height)

        let padding: CGFloat = 5
        let container = UIView(frame: CGRect(x:0, y: 0, width: size.width + padding, height: size.height))
        container.addSubview(myButton)

        myButton.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            myButton.topAnchor.constraint(equalTo: container.topAnchor),
            myButton.leftAnchor.constraint(equalTo: container.leftAnchor),
            myButton.bottomAnchor.constraint(equalTo: container.bottomAnchor),
            myButton.rightAnchor.constraint(equalTo: container.rightAnchor, constant: -padding),
        ])

        textField.rightViewMode = .always
        textField.rightView = container
    }
}

Die obigen Antworten funktionieren bei mir nicht, dieser funktioniert.
Mark Dylan B Mercado

1

// Setze die rechte Ansicht von UITextField, schnell 4.2TxtPass.rightViewMode = UITextField.ViewMode.always let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 18, height: 18)) imageView.contentMode = UIView.ContentMode.scaleAspectFit let image = UIImage(named: "hidepass") imageView.image = image let rightView = UIView(frame: CGRect(x: 0, y: 0, width: 28, height: 18)) rightView.addSubview(imageView) rightView.contentMode = UIView.ContentMode.left TxtPass.rightView = rightView


0

Ein Trick: Fügen Sie UITextField eine UIView mit UIImageView als rightView hinzu. Diese UIView muss größer sein. Platzieren Sie nun die UIImageView links davon. Es wird also eine Polsterung des Raums von rechts geben.

// Add a UIImageView to UIView and now this UIView to UITextField - txtFieldDate
UIView *viewRightIntxtFieldDate = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 30)]; 
// (Height of UITextField is 30px so height of viewRightIntxtFieldDate = 30px)
UIImageView *imgViewCalendar = [[UIImageView alloc] initWithFrame:CGRectMake(0, 10, 10, 10)];
[imgViewCalendar setImage:[UIImage imageNamed:@"calendar_icon.png"]];
[viewRightIntxtFieldDate addSubview:imgViewCalendar];
txtFieldDate.rightViewMode = UITextFieldViewModeAlways;
txtFieldDate.rightView = viewRightIntxtFieldDate;

0

Am einfachsten ist es, das Textfeld als RoundRect anstelle von Custom zu ändern und die Magie zu sehen. :) :)


0

für Swift2 benutze ich

...
        self.mSearchTextField.leftViewMode = UITextFieldViewMode.Always
        let searchImg = UIImageView(image: UIImage(named: "search.png"))
        let size = self.mSearchTextField.frame.height
        searchImg.frame = CGRectMake(0, 0, size,size)
        searchImg.contentMode = UIViewContentMode.ScaleAspectFit
        self.mSearchTextField.leftView = searchImg
...

0
...
textField.rightView = UIImageView(image: ...)
textField.rightView?.contentMode = .top
textField.rightView?.bounds.size.height += 10
textField.rightViewMode = .always
...

0

Einfacher Ansatz:

textField.rightViewMode = .always
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 25, height: 15))
textField.contentMode = .scaleAspectFit
imageView = UIImage(named: "imageName")
textField.rightView = imageView

Hinweis: Die Höhe sollte kleiner als die Breite sein, um eine horizontale Polsterung zu ermöglichen.


0

Mir ist klar, dass dies ein alter Beitrag ist und diese Antwort etwas spezifisch für meinen Anwendungsfall ist, aber ich habe sie veröffentlicht, falls andere nach einer ähnlichen Lösung suchen. Ich möchte die leftView oder rightView eines UITextField verschieben, aber ich füge keine Bilder in sie ein und möchte keine fest codierten Konstanten.

In meiner Benutzeroberfläche muss die Schaltfläche zum Löschen des Textfelds ausgeblendet und eine UIActivityIndicatorView angezeigt werden, in der sich die Schaltfläche zum Löschen befand.

Ich füge dem einen Spinner hinzu rightView, aber nach dem Auspacken (unter iOS 13) wird er um 20 Pixel nach rechts verschoben clearButton. Ich verwende keine magischen Zahlen, da sich die Position von clearButton und rightView von Apple jederzeit ändern kann. Die Absicht des UI-Designs ist "Spinner, wo sich die Schaltfläche zum Löschen befindet". Meine Lösung bestand also darin, UITextField zu unterklassifizieren und zu überschreiben rightViewRect(forBounds).

override func rightViewRect(forBounds bounds: CGRect) -> CGRect {

    // Use clearButton's rectangle
    return self.clearButtonRect(forBounds: bounds)
}

Unten finden Sie ein Arbeitsbeispiel (ohne Storyboard):

//------------------------------------------------------------------------------
class myCustomTextField: UITextField {

    override func rightViewRect(forBounds bounds: CGRect) -> CGRect {

        // Use clearButton rectangle
        return self.clearButtonRect(forBounds: bounds)
    }
}

//------------------------------------------------------------------------------
class myViewController: UIViewController {

    var activityView: UIActivityIndicatorView = {
        let activity = UIActivityIndicatorView()
        activity.startAnimating()
        return activity
    }()

    @IBOutlet weak var searchTextField: myCustomTextField!

    //------------------------------------------------------------------------------
    // MARK: - Lifecycle
    //------------------------------------------------------------------------------
    override func viewDidLoad() {

        super.viewDidLoad()

        searchTextField.rightView = activityView
        searchTextField.rightViewMode = .never // Hide spinner
        searchTextField.clearButtonMode = .never // Hide clear button

        setupUIForTextEntry()
    }

    // ...
    // More code to switch between user text entry and "search progress" 
    // by calling setupUI... functions below
    // ...

    //------------------------------------------------------------------------------
    // MARK: - UI
    //------------------------------------------------------------------------------
    func setupUIForTextEntry() {

        // Hide spinner
        searchTextField.rightViewMode = .never

        // Show clear button
        searchTextField.clearButtonMode = .whileEditing
        searchTextField.becomeFirstResponder()
    }

    //------------------------------------------------------------------------------
    func setupUIForSearching() {

        // Show spinner
        searchTextField.rightViewMode = .always

        // Hide clear button
        searchTextField.clearButtonMode = .never
        searchTextField.resignFirstResponder()
    }

    //------------------------------------------------------------------------------

}

//------------------------------------------------------------------------------
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.