UITextfield leftView / rightView padding su iOS7


94

Le viste leftView e rightView di un UITextField su iOS7 sono molto vicine al bordo del campo di testo.

Come posso aggiungere un po 'di imbottitura (orizzontale) a quegli elementi?

Ho provato a modificare la cornice, ma non ha funzionato

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

Per favore, nota che non sono interessato ad aggiungere padding al testo del campo di testo, come questo Imposta padding per UITextField con UITextBorderStyleNone


possibile duplicato del riquadro
Zorayr

1
No, si tratta di chiedere informazioni sul rientro dell'immagine visualizzata come leftView in un campo di testo. Non indentare il testo stesso. Prova il suo codice e vedrai che l'impostazione leftView su un'immagine posiziona quell'immagine contro il bordo sinistro del campo di testo, senza riempimento. Sembra brutto.
pietra

Risposte:


90

Ci stavo solo lavorando da solo e ho usato questa soluzione:

- (CGRect) rightViewRectForBounds:(CGRect)bounds {

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

Questo sposterà l'immagine da destra di 10 invece di avere l'immagine schiacciata contro il bordo in iOS 7.

Inoltre, questo era in una sottoclasse di UITextField, che può essere creata da:

  1. Crea un nuovo file che sia una sottoclasse UITextFieldanziché quella predefinitaNSObject
  2. Aggiungi un nuovo metodo denominato - (id)initWithCoder:(NSCoder*)coderper impostare l'immagine

    - (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. Potrebbe essere necessario importare #import <QuartzCore/QuartzCore.h>

  4. Aggiungi il rightViewRectForBoundsmetodo sopra

  5. In Interface Builder, fare clic sul campo di testo che si desidera sottoclasse e modificare l'attributo della classe con il nome di questa nuova sottoclasse


come usare IBDesignable per questo stesso?
riddhi

per la versione più recente o se si sta visualizzando questo nel 2020. visita: stackoverflow.com/a/55041786/6596443
AKINNUBI Abiola SYLVESTER

167

Una soluzione molto più semplice, che si avvale di 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
Puoi anche usare ScaleAspectFit invece di center ... se la dimensione dell'immagine non corrisponde al fotogramma esatto.
Mihir Mehta,

Ho usato il tuo esempio per UIButton (invece di UIImageView) mentre il suo tipo è InfoLight.
OhadM

Ho scoperto che ".right" invece di ".center" fa sembrare più simile a una barra di ricerca incorporata come quella nell'app Contatti. Ottima soluzione su questo, grazie per averlo postato.
James Toomey

Oppure, se hai bisogno di essere preciso nella ricreazione del design, metti l'immagine a sinistra e poi aumenta la larghezza per ottenere un riempimento esatto
jovanjovanovic

4
Questo sembra non funzionare più con iOS 13 e Xcode 11 Beta 7. Tuttavia, funziona bene su iOS 11/12.
PatrickDotStar

49

Il modo più semplice è aggiungere un UIView a leftView / righView e aggiungere un ImageView a UIView, regolare l'origine di ImageView all'interno di UIView ovunque tu voglia, questo ha funzionato per me come un fascino. Richiede solo poche righe di codice

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 non funziona ma questa risposta funziona a meraviglia!
nigong

14

Funziona alla grande per 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

impossibile convertire il valore di tipo "stringa" nel tipo di argomento previsto "UIImage?"

7

Questo funziona per me

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

Possa aiutarti.


6

Mi piace questa soluzione perché risolve il problema con una singola riga di codice

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

Nota: .. o 2 se si considera di includere QuartzCore una riga :)


1
Questo sposta anche il confine
Softlion

1
ma non risolve il problema con il riempimento destro solo il problema con il riempimento sinistro
carmen_munich

1
Ho ottenuto un risultato migliore usando rightView.layer.sublayerTransform = CATransform3DMakeTranslation (-10.0f, 0.0f, 0.0f), ma +1 per il metodo
Thibaud David

Tieni presente che questo sposterà anche il pulsante "cancella" del campo di testo a destra, che può spingerlo oltre il bordo del campo di testo. Se non hai bisogno del pulsante Clear, questo è un ottimo approccio, altrimenti forse no.
Tom Harrington,

4

Il modo migliore per farlo è semplicemente creare una classe usando la sottoclasse di UITextField e nel file .m

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

}

in questo modo vai al tuo storyboard o xib e fai clic su Identity Inspector e sostituisci UITextfield con la tua "CustomTextField" nell'opzione di classe.

Nota: se fornisci semplicemente il riempimento con layout automatico per il campo di testo, la tua applicazione non verrà eseguita e mostrerà solo lo schermo vuoto.


4

Invece di manipolare imageView o image possiamo sovrascrivere un metodo fornito da apple per rightView.

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

e allo stesso modo possiamo sovrascrivere sotto func per la vista sinistra.

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

}

3

L'ho trovato da qualche parte ...

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

[self addSubview:itemDescription];

4
Ciò aggiunge solo il riempimento al testo, che non è ciò che il richiedente sta cercando. Non vuole una visuale sinistra chiara. Vuole un'immagine visualizzata come leftView.
pietra

Puoi semplicemente aggiungere l'immagine nel paddingView.
Matheus Weber

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

Ti consigliamo di:

  • Sottoclasse UITextField
  • Scrivi un metodo invalidato all'interno del campo di testo sottoclasse
  • Nel metodo invalidate, crea un'immagine UIView più grande della tua immagine
  • Posiziona la tua immagine all'interno della vista
  • Assegna la vista a UITextField.rightView

2

Ecco una soluzione:

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

1

Crea una classe UITextField personalizzata e usa quella classe invece di UITextField. Override - (CGRect) textRectForBounds: (CGRect) limiti per impostare il rect di cui hai bisogno

Esempio

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

1

L'esempio seguente serve per aggiungere un riempimento orizzontale a una vista sinistra che sembra essere un'icona: puoi utilizzare l'approccio simile per aggiungere un riempimento a qualsiasi vista UIViewche desideri utilizzare come vista sinistra del campo di testo.

UITextFieldSottoclasse interna :

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

Sebbene qui siamo una sottoclasse UITextField, credo che questo sia l'approccio più pulito.


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

Se UITextFieldè incorporato in a UISearchBar, come si dice UISearchBara utilizzare la propria UITextFieldsottoclasse?
crishoj

1

grazie ragazzi per le vostre risposte, con mia sorpresa nessuno di loro si adattava davvero alla giusta immagine di visualizzazione al mio campo di testo pur fornendo il riempimento necessario. poi ho pensato di utilizzare la modalità AspectFill e sono avvenuti miracoli. per i futuri cercatori, ecco cosa ho usato:

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;

il 35 nel riquadro della mia visualizzazione dell'immagine rappresenta l'altezza del mio campo di testo e-mail, sentiti libero di adattarlo alle tue esigenze.


1

Ho avuto questo problema io stesso e di gran lunga la soluzione più semplice è modificare la tua immagine per aggiungere semplicemente il riempimento a ciascun lato dell'immagine!

Ho appena modificato la mia immagine png per aggiungere un riempimento trasparente di 10 pixel e funziona bene, senza alcuna codifica!


1

Se stai usando un UIImageView come leftView, devi usare questo codice:

Attenzione: non utilizzare viewWillAppear o viewDidAppear all'interno

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

Ho creato un metodo personalizzato nella mia classe ViewController, come mostrato di seguito:

- (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;
}

Ora posso chiamare quel metodo all'interno di ( viewDidLoadmetodo) e inviare uno qualsiasi dei miei TextFieldsa quel metodo e aggiungere imbottitura sia per destra che per sinistra e dare colori al testo e allo sfondo scrivendo solo una riga di codice, come segue:

[self modifyTextField:self.firstNameTxtFld];

Funzionava perfettamente su iOS 7! Spero che funzioni ancora anche su iOS 8 e 9!

So che l'aggiunta di troppe visualizzazioni potrebbe rendere questo oggetto un po 'più pesante da caricare. Ma quando ero preoccupato per la difficoltà di altre soluzioni, mi sono trovato più sbilanciato a questo metodo e più flessibile nell'usarlo. ;)

Spero che questa risposta possa essere utile o utile per trovare un'altra soluzione per qualcun altro.

Saluti!


1

Questo funziona per me proprio come cerco:

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

Poiché iOS 13 e Xcode 11 questa è l'unica soluzione che funziona per noi.

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

le risposte sopra non funzionano per me, questo funziona.
Mark Dylan B Mercado

1

// Imposta la vista destra di UITextField, swift 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

Un trucco: aggiungi un UIView contenente UIImageView a UITextField come rightView. Questa UIView deve essere di dimensioni maggiori, ora posiziona UIImageView a sinistra di essa. Quindi ci sarà un'imbottitura di spazio da destra.

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

Il modo più semplice è cambiare il campo di testo come RoundRect invece di Personalizzato e vedere la magia. :)


0

per Swift2, io uso

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

Approccio semplice:

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

Nota: l'altezza deve essere inferiore alla larghezza per consentire il riempimento orizzontale.


0

Mi rendo conto che questo è un vecchio post e questa risposta è un po 'specifica per il mio caso d'uso, ma l'ho postata nel caso in cui altri stessero cercando una soluzione simile. Voglio spostare leftView o rightView di un UITextField ma non inserisco immagini in essi e non voglio costanti hard coded.

La mia interfaccia utente richiede di nascondere il pulsante di cancellazione del campo di testo e di visualizzare un UIActivityIndicatorView in cui si trovava il pulsante di cancellazione.

Aggiungo uno spinner al rightView, ma fuori dalla scatola (su iOS 13) viene spostato di 20 pixel a destra del clearButton. Non mi piace usare numeri magici poiché la posizione di clearButton e rightView è soggetta a modifiche in qualsiasi momento da parte di Apple. L'intento di progettazione dell'interfaccia utente è "spinner dove si trova il pulsante di cancellazione", quindi la mia soluzione è stata quella di sottoclassare UITextField e sovrascrivere rightViewRect(forBounds).

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

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

Di seguito è riportato un esempio funzionante (senza 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()
    }

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

}

//------------------------------------------------------------------------------
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.