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

sous zéro
la source
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

AngeloS
la source
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
TTillage
la source
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];
vishal dharankar
la source
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
Andy
la source
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.

Ashu
la source
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 :)

Jordi Corominas
la source
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.

Anuj Kumar Rai
la source
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*/

}
Pranav Gupta
la source
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];
Expression régulière
la source
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
bkSwifty
la source
2

Voici une solution:

 UIView *paddingTxtfieldView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 42)]; // what ever you want 
 txtfield.leftView = paddingTxtfieldView;
 txtfield.leftViewMode = UITextFieldViewModeAlways;
Dev Patel
la source
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;
}
Kedar
la source
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.

Zorayr
la source
1
- (CGRect)rightViewRectForBounds:(CGRect)bounds
{
    return CGRectMake(bounds.size.width - 40, 0, 40, bounds.size.height);
}
carmen_munich
la source
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.

carlos16196
la source
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!

Richard
la source
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;
}
Zeeshan
la source
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é!

Randika Vishman
la source
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
}
Aleksandr Skorotkin
la source
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
    }
}
PatrickDotStar
la source
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

NSurajit
la source
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;
Suraj Mirajkar
la source
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. :)

Shilpa
la source
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
...
Haiyuan
la source
0
...
textField.rightView = UIImageView(image: ...)
textField.rightView?.contentMode = .top
textField.rightView?.bounds.size.height += 10
textField.rightViewMode = .always
...
Rafael Sachetto
la source
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.

Mukesh Shakya
la source
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()
    }

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

}

//------------------------------------------------------------------------------
Swany
la source