web-dev-qa-db-fra.com

UITextField secureTextEntry balles avec une police personnalisée?

J'utilise une police personnalisée dans une UITextField, sur laquelle secureTextEntry est activé. Lorsque je tape dans la cellule, je vois les puces dans la police de mon choix, mais lorsque le champ perd le focus, ces puces reviennent à la police standard du système. Si je tape à nouveau sur le champ, ils repassent sur ma police, et ainsi de suite.

Pourrais-je m'assurer qu'ils continuent d'afficher les puces de la police personnalisée, même lorsque le champ est flou?

enter image description hereenter image description here

39
Luke

Une sous-classe qui résout ce problème. Créez une variable arbitraire UITextField, puis définissez la propriété secure sur YES (via KVC dans IB).

En réalité, il met en œuvre un commentaire suggéré par lukech . Lorsque le champ de texte termine son édition, il bascule vers un champ de texte arbitraire, puis définit un ensemble de points dans et un hack dans un accesseur text pour toujours obtenir le texte actuel du champ.

@interface SecureTextFieldWithCustomFont : UITextField
@property (nonatomic) BOOL secure;
@property (nonatomic, strong) NSString *actualText;
@end


@implementation SecureTextFieldWithCustomFont


-(void)awakeFromNib
{
    [super awakeFromNib];

    if (self.secureTextEntry)
    {
        // Listen for changes.
        [self addTarget:self action:@selector(editingDidBegin) forControlEvents:UIControlEventEditingDidBegin];
        [self addTarget:self action:@selector(editingDidChange) forControlEvents:UIControlEventEditingChanged];
        [self addTarget:self action:@selector(editingDidFinish) forControlEvents:UIControlEventEditingDidEnd];
    }
}

-(NSString*)text
{
    if (self.editing || self.secure == NO)
    { return [super text]; }

    else
    { return self.actualText; }
}

-(void)editingDidBegin
{
    self.secureTextEntry = YES;
    self.text = self.actualText;
}

-(void)editingDidChange
{ self.actualText = self.text; }

-(void)editingDidFinish
{
    self.secureTextEntry = NO;
    self.actualText = self.text;
    self.text = [self dotPlaceholder];
}

-(NSString*)dotPlaceholder
{
    int index = 0;
    NSMutableString *dots = @"".mutableCopy;
    while (index < self.text.length)
    { [dots appendString:@"•"]; index++; }
    return dots;
}


@end

Peut être augmenté pour fonctionner avec des instanciations non NIB, la gestion des valeurs par défaut, etc., mais vous avez probablement l’idée.

17
Geri

Pour ceux qui ont des difficultés à perdre des polices personnalisées lors du basculement de secureTextEntry, j'ai trouvé une solution de contournement (j'utilise le SDK iOS 8.4). J'essayais de créer une bascule pour afficher/masquer un mot de passe dans un UITextField. Chaque fois que je changeais secureTextEntry = NO, ma police personnalisée était bouchée, et seul le dernier caractère affichait la police correcte. Quelque chose de génial se passe vraiment avec ça, mais voici ma solution:

-(void)showPassword {
    [self.textField resignFirstResponder];
    self.textField.secureTextEntry = NO;
}

Le premier intervenant doit être démissionné pour une raison quelconque. Vous ne semblez pas avoir besoin de démissionner du premier répondant lorsque vous définissez SecureTextEntry sur OUI, uniquement lorsque vous définissez NON.

11
Joshua Haines

Le problème réel semble être que la vue d'édition (UITextFieldne le fait pas dessine son propre texte lors de la modification) utilise des puces (U + 2022) pour dessiner des caractères retranchés, alors que UITextField utilise des cercles noirs (U + 25CF). Je suppose que dans les polices par défaut, ces caractères se ressemblent.

Voici une solution de rechange pour les personnes intéressées, qui utilise une sous-classe de champ de texte personnalisé, mais ne nécessite pas de jongler avec la propriété de texte ou une autre configuration spéciale. OMI, cela garde les choses relativement propres.

@interface MyTextField : UITextField
@end

@implementation MyTextField

- (void)drawTextInRect:(CGRect)rect
{
    if (self.isSecureTextEntry)
    {
        NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
        paragraphStyle.alignment = self.textAlignment;

        NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
        [attributes setValue:self.font forKey:NSFontAttributeName];
        [attributes setValue:self.textColor forKey:NSForegroundColorAttributeName];
        [attributes setValue:paragraphStyle forKey:NSParagraphStyleAttributeName];

        CGSize textSize = [self.text sizeWithAttributes:attributes];

        rect = CGRectInset(rect, 0, (CGRectGetHeight(rect) - textSize.height) * 0.5);
        rect.Origin.y = floorf(rect.Origin.y);

        NSMutableString *redactedText = [NSMutableString new];
        while (redactedText.length < self.text.length)
        {
            [redactedText appendString:@"\u2022"];
        }

        [redactedText drawInRect:rect withAttributes:attributes];
    }
    else
    {
        [super drawTextInRect:rect];
    }
}

@end
9
Austin

Bien qu’il s’agisse d’un bogue iOS (et nouveau dans iOS 7, j’ajouterais), j’ai un autre moyen de le contourner qui pourrait être considéré comme acceptable. La fonctionnalité est toujours légèrement dégradée mais pas beaucoup. 

Fondamentalement, l’idée est de définir la police sur le style/famille de police par défaut chaque fois que le champ contient quelque chose; mais lorsque rien n'est entré, réglez-le sur votre police personnalisée. (La taille de la police peut être laissée seule, car c'est la famille/le style, pas la taille, qui pose problème). Interrompez chaque changement de la valeur du champ et définissez la police en conséquence à ce moment-là. Ensuite, le faible texte "indice" lorsque rien n'est entré contient la police que vous voulez (personnalisée); mais quand quelque chose est entré (que vous soyez en train d’éditer ou non), on utilisera par défaut (Helvetica). Puisque les balles sont des balles, cela devrait bien paraître.

Le seul inconvénient est que les caractères, tels que vous les tapez avant d’être remplacés par des puces, utilisent la police par défaut (Helvetica). Ce n'est que pour une fraction de seconde par personnage cependant. Si cela est acceptable, cette solution fonctionne.

3
RedRedSuit
[passWordTextField resignFirstResponder];
passWordTextField.secureTextEntry = !passWordTextField.secureTextEntry;
[passWordTextField becomeFirstResponder];

C'est le moyen le plus rapide de résoudre ce bug

1
AaronTKD

J'ai trouvé un truc pour ce problème.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
   if ([textField tag]== TAG_PASS || [textField tag]== TAG_CPASS)
    {
       // To fix password dot size
        if ([[textField text] isEqualToString:@"" ])
        {
          [textField setText:@" "];
          [textField resignFirstResponder];
          [textField becomeFirstResponder];
          [textField setText:@""];
        }  
    }
}
1
Parul Jaisansaria

Un champ de texte secureTextEntry peut être totalement évité:

NSString *pin = @"";
BOOL pasting = FALSE;
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if(!pasting) {
        pin = [pin stringByReplacingCharactersInRange:range withString:string];

        // Bail out when deleting a character
        if([string length] == 0) {
            return YES;
        }

        pasting = TRUE;
        [textField paste:@"●"];

        return NO;
    } else {
        pasting = FALSE;
        return YES;
    }
}
0
Randomblue

iOS agit un peu étrange quand il s'agit de polices personnalisées. Essayez de supprimer "Ajuster" à ce champ de texte. Si cela ne fonctionne pas, je suppose que ce qui vous préoccupe, c'est l'augmentation de la taille de la police.

Une solution simple pour cela serait:

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    if(textField.secureTextEntry)
    {
        [textField setFont:[UIFont fontWithName:@"Helvetica-Bold" size:10.0]];
    }
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
    if(textField.secureTextEntry)
    {
        [textField setFont:[UIFont fontWithName:@"Helvetica-Bold" size:10.0]];
    }
}

Vous aurez besoin de jouer avec la taille un peu pour qu'il ne semble pas y avoir de changement de taille lorsque vous perdez la concentration sur la UITextField.

Si vous rencontrez un problème d'espacement important entre les caractères, comme dans la question modifiée, la solution la plus simple (et un peu moche) consiste à créer une image Bullet qui corresponde à la taille et à l'espacement ci-dessus et qui correspond au nombre de caractères entrés par l'utilisateur. apparaît lorsque l'utilisateur quitte la UITextField.

0
Segev

Je vous recommande de resignFirstResponder avant de modifier scureTextEntry, puis de redevenir FirstFrponder car il est publié ici: https://stackoverflow.com/a/34777286/1151916

0
Ramis