UITextfield leftView / rightView padding sur iOS7


94

Les vues leftView et rightView d'un UITextField sur iOS7 sont vraiment proches de la bordure du champ de texte.

Comment puis-je ajouter un rembourrage (horizontal) à ces éléments?

J'ai essayé de modifier le cadre, mais cela n'a pas fonctionné

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

Veuillez noter que je ne suis pas intéressé par l'ajout de remplissage au texte du champ de texte, comme celui-ci Définir le remplissage pour UITextField avec UITextBorderStyleNone


duplication possible de l' encart de texte pour UITextField?
Zorayr

1
Non, il s'agit de mettre en retrait l'image affichée en tant que vue de gauche dans un champ de texte. Ne pas mettre en retrait le texte lui-même. Essayez son code et vous verrez que le paramètre leftView sur une image place cette image contre le bord gauche du champ de texte, sans remplissage. Ça a l'air moche.
pierre du

Réponses:


90

Je travaillais juste dessus moi-même et j'ai utilisé cette solution:

- (CGRect) rightViewRectForBounds:(CGRect)bounds {

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

Cela déplacera l'image de la droite de 10 au lieu d'avoir l'image pressée contre le bord dans iOS 7.

De plus, cela faisait partie d'une sous-classe de UITextField, qui peut être créée par:

  1. Créer un nouveau fichier qui est une sous-classe de UITextFieldau lieu de la valeur par défautNSObject
  2. Ajouter une nouvelle méthode nommée - (id)initWithCoder:(NSCoder*)coderpour définir l'image

    - (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. Vous devrez peut-être importer #import <QuartzCore/QuartzCore.h>

  4. Ajoutez la rightViewRectForBoundsméthode ci-dessus

  5. Dans Interface Builder, cliquez sur le TextField que vous souhaitez sous-classe et remplacez l'attribut de classe par le nom de cette nouvelle sous-classe


comment utiliser IBDesignable pour cela?
riddhi

pour la dernière version ou si vous consultez ceci en 2020. visitez: stackoverflow.com/a/55041786/6596443
AKINNUBI ABIOLA SYLVESTER

167

Une solution beaucoup plus simple, qui profite de 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;

Dans 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
Vous pouvez également utiliser ScaleAspectFit au lieu du centre ... si la taille de l'image ne correspond pas au cadre exact.
Mihir Mehta le

J'ai utilisé votre exemple pour UIButton (au lieu de UIImageView) alors que son type est InfoLight.
OhadM le

J'ai trouvé que ".right" au lieu de ".center" le fait ressembler davantage à une barre de recherche intégrée telle que celle de l'application Contacts. Excellente solution à ce sujet, merci de l'avoir publiée.
James Toomey

Ou si vous avez besoin d'être précis dans les loisirs de conception, mettez l'image à gauche, puis augmentez la largeur pour obtenir un rembourrage exact
jovanjovanovic

4
Cela ne semble plus fonctionner avec iOS 13 et Xcode 11 Beta 7. Cela fonctionne bien sur iOS 11/12.
PatrickDotStar

49

Le moyen le plus simple est d'ajouter un UIView à leftView / righView et d'ajouter un ImageView à UIView, d'ajuster l'origine de ImageView dans UIView où vous le souhaitez, cela a fonctionné pour moi comme un charme. Il ne nécessite que quelques lignes de code

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 ça ne marche pas mais cette réponse fonctionne comme un charme!
nigong

14

Cela fonctionne très bien pour 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

impossible de convertir la valeur de type 'chaîne' en type d'argument attendu 'UIImage? "

7

Cela fonctionne pour moi

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

Que cela vous aide.


6

J'aime cette solution car elle résout le problème avec une seule ligne de code

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

Remarque: .. ou 2 si vous envisagez d'inclure QuartzCore une ligne :)


1
Cela déplace également la frontière
Softlion

1
mais ne résout pas le problème avec le rembourrage droit seulement le problème de rembourrage gauche
carmen_munich

1
J'ai eu un meilleur résultat en utilisant rightView.layer.sublayerTransform = CATransform3DMakeTranslation (-10.0f, 0.0f, 0.0f), mais +1 pour la méthode
Thibaud David

Gardez à l'esprit que cela déplacera également le bouton "Effacer" du champ de texte vers la droite, ce qui peut le pousser au-delà du bord du champ de texte. Si vous n'avez pas besoin du bouton d'effacement, c'est une excellente approche, sinon peut-être pas.
Tom Harrington

4

La meilleure façon de faire est simplement de créer une classe en utilisant la sous-classe de UITextField et dans le fichier .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;

}

en faisant cela, allez dans votre storyboard ou xib et cliquez sur l'inspecteur d'identité et remplacez UITextfield par votre propre option "CustomTextField" dans la classe.

Remarque: Si vous donnez simplement un remplissage avec une mise en page automatique pour le champ de texte, votre application ne s'exécutera pas et affichera uniquement un écran vide.


4

Au lieu de manipuler imageView ou image, nous pouvons remplacer une méthode fournie par apple pour 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
}}

et de la même manière, nous pouvons remplacer ci-dessous func pour la vue de gauche.

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

}

3

J'ai trouvé ça quelque part ...

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

[self addSubview:itemDescription];

4
Cela ajoute simplement un remplissage au texte, ce qui n'est pas ce que le demandeur recherche. Il ne veut pas d'une vue de gauche claire. Il veut une image affichée comme vue de gauche.
pierre du

Vous pouvez simplement ajouter l'image dans le 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
    }
}

Vous voudrez:

  • Sous-classe UITextField
  • Ecrire une méthode invalide dans le champ de texte sous-classé
  • Dans la méthode invalidate, créez un UIView plus grand que votre image
  • Placez votre image dans la vue
  • Attribuer la vue à UITextField.rightView

2

Voici une solution:

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

1

Créez une classe UITextField personnalisée et utilisez cette classe au lieu de UITextField. Override - (CGRect) textRectForBounds: (CGRect) limites pour définir le rect dont vous avez besoin

Exemple

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

1

L'exemple ci-dessous concerne l'ajout d'un remplissage horizontal à une vue de gauche qui se trouve être une icône - vous pouvez utiliser la même approche pour ajouter un remplissage à tout ce UIViewque vous souhaitez utiliser comme vue de gauche du champ de texte.

À l'intérieur de la UITextFieldsous-classe:

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

Bien que nous soyons UITextFieldici un sous- classement, je pense que c'est l'approche la plus claire.


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

Si le UITextFieldest incorporé dans a UISearchBar, comment dites-vous au UISearchBard'utiliser votre UITextFieldsous-classe?
crishoj

1

merci les gars pour vos réponses, à ma grande surprise, aucun d'entre eux n'a vraiment adapté la bonne image de vue à mon champ de texte tout en fournissant le rembourrage nécessaire. puis j'ai pensé à utiliser le mode AspectFill et des miracles se sont produits. pour les futurs chercheurs, voici ce que j'ai utilisé:

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;

le 35 dans le cadre de mon imageview représente la hauteur de mon emailTextfield, n'hésitez pas à l'ajuster à vos besoins.


1

J'ai eu ce problème moi-même, et de loin la solution la plus simple est de modifier votre image pour simplement ajouter un rembourrage de chaque côté de l'image!

Je viens de modifier mon image png pour ajouter un remplissage transparent de 10 pixels, et cela fonctionne bien, sans aucun codage!


1

Si vous utilisez un UIImageView comme leftView, vous devez utiliser ce code:

Attention: n'utilisez pas inside viewWillAppear ou 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

J'ai créé une méthode personnalisée dans ma classe ViewController, comme indiqué ci-dessous:

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

Maintenant, je peux appeler cette méthode à l'intérieur de ( viewDidLoadméthode) et envoyer n'importe lequel de mes TextFieldsà cette méthode et ajouter un remplissage pour la droite et la gauche, et donner des couleurs de texte et d'arrière-plan en écrivant une seule ligne de code, comme suit:

[self modifyTextField:self.firstNameTxtFld];

Cela a parfaitement fonctionné sur iOS 7! J'espère que cela fonctionne toujours sur iOS 8 et 9 aussi!

Je sais que l'ajout de trop de vues peut rendre cet objet un peu plus lourd à charger. Mais lorsque je suis préoccupé par la difficulté des autres solutions, je me suis retrouvé plus partisan de cette méthode et plus flexible dans son utilisation. ;)

J'espère que cette réponse pourra être utile ou utile pour trouver une autre solution à quelqu'un d'autre.

À votre santé!


1

Cela fonctionne pour moi, tout comme je recherche:

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

Depuis iOS 13 et Xcode 11, c'est la seule solution qui fonctionne pour nous.

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

les réponses ci-dessus ne fonctionnent pas pour moi, celle-ci fonctionne.
Mark Dylan B Mercado

1

// Définir Rightview de 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

Une astuce: ajoutez un UIView contenant UIImageView à UITextField en tant que rightView. Cette UIView doit être plus grande, placez maintenant l'UIImageView à gauche de celle-ci. Il y aura donc un rembourrage d'espace à partir de la droite.

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

Le moyen le plus simple est simplement de changer le champ de texte en RoundRect au lieu de Custom et de voir la magie. :)


0

pour Swift2, j'utilise

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

Approche simple:

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

Remarque: la hauteur doit être inférieure à la largeur pour permettre un remplissage horizontal.


0

Je me rends compte qu'il s'agit d'un ancien article et que cette réponse est un peu spécifique à mon cas d'utilisation, mais je l'ai publiée au cas où d'autres chercheraient une solution similaire. Je veux déplacer leftView ou rightView d'un UITextField mais je n'y mets pas d'images et je ne veux pas de constantes codées en dur.

Mon interface utilisateur demande de masquer le bouton d'effacement du champ de texte et d'afficher un UIActivityIndicatorView à l'emplacement du bouton d'effacement.

J'ajoute un spinner au rightView, mais hors de la boîte (sur iOS 13), il est décalé de 20 pixels vers la droite du clearButton. Je n'aime pas utiliser des nombres magiques car la position du clearButton et de rightView est susceptible d'être modifiée à tout moment par Apple. L'intention de conception de l'interface utilisateur est «spinner où se trouve le bouton d'effacement», donc ma solution était de sous-classer UITextField et de le remplacer rightViewRect(forBounds).

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

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

Voici un exemple de travail (sans 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()
    }

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

}

//------------------------------------------------------------------------------
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.