ios - tamaño - Viñetas UITTextField secureTextEntry con una fuente personalizada?
tamaño de letra html (9)
El problema real parece ser que la vista de edición ( UITextField
no dibuja su propio texto mientras se edita) usa viñetas (U + 2022) para dibujar caracteres redactados, mientras que UITextField
usa círculos negros (U + 25CF). Supongo que en las fuentes predeterminadas, estos personajes tienen el mismo aspecto.
Aquí hay una solución alternativa para cualquier persona interesada, que utiliza una subclase de campo de texto personalizada, pero que no requiere el malabarismo de la propiedad de texto u otra configuración especial. OMI, esto mantiene las cosas relativamente limpias.
@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
Estoy usando una fuente personalizada en un UITextField
, que tiene secureTextEntry
activado. Cuando escribo en la celda, veo las viñetas en la fuente elegida, pero cuando el campo pierde el foco, esas viñetas vuelven a la fuente estándar del sistema. Si vuelvo a tocar el campo, vuelven a mi fuente, y así sucesivamente.
¿Existe alguna forma de garantizar que continúen mostrando las viñetas de la fuente personalizada, incluso cuando el campo esté desenfocado?
Encontré un truco para este problema.
- (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:@""];
}
}
}
Para aquellos que tienen problemas con la pérdida de fuentes personalizadas al alternar entre SecureTextEntry, encontré una solución temporal (estoy usando iOS 8.4 SDK). Estaba tratando de alternar para mostrar / ocultar una contraseña en un UITextField. Cada vez que secureTextEntry = NO
mi fuente personalizada se borked, y solo el último carácter mostraba la fuente correcta. Algo funky definitivamente está pasando con esto, pero esta es mi solución:
-(void)showPassword {
[self.textField resignFirstResponder];
self.textField.secureTextEntry = NO;
}
El primer respondedor necesita ser resignado por alguna razón. Parece que no necesita renunciar al primer respondedor cuando establece secureTextEntry en YES, solo cuando establece NO.
Recomiendo que resignFirstResponder antes de cambiar scureTextEntry y luego convertirse en FirebirdResponder nuevamente, ya que se publica aquí: https://.com/a/34777286/1151916
Si bien este es un error de iOS (y nuevo en iOS 7, debería agregar), tengo otra forma de solucionarlo que uno podría considerar aceptable. La funcionalidad aún está ligeramente degradada, pero no por mucho.
Básicamente, la idea es establecer la fuente de la familia / estilo de fuente predeterminada siempre que el campo tenga algo ingresado; pero cuando no se ingresa nada, configúrelo en su fuente personalizada. (El tamaño de fuente se puede dejar solo, ya que es la familia / estilo, no el tamaño, que tiene errores.) Atrape cada cambio del valor del campo y configure la fuente en consecuencia en ese momento. Luego, el débil texto "sugerencia" cuando no se ingresa nada tiene la fuente que desea (personalizada); pero cuando se ingresa algo (ya sea que esté editando o no) usará el valor predeterminado (Helvetica). Como las balas son balas, esto debería verse bien.
El único inconveniente es que los caracteres, a medida que escribe antes de ser reemplazado por viñetas, utilizarán la fuente predeterminada (Helvetica). Eso es solo por una fracción de segundo por personaje. Si eso es aceptable, entonces esta solución funciona.
Un campo de texto secureTextEntry
se puede evitar por completo:
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;
}
}
Una subclase que funciona alrededor de este problema. Cree un UITextField
arbitrario , luego establezca la propiedad secure
en YES
(a través de KVC en IB).
En realidad, implementa un comentario sugerido por lukech . Cuando el campo de texto termina de editar, cambia a un campo de texto arbitrario, luego establece una gran cantidad de puntos, y algunos piratean el acceso de text
para obtener siempre el texto real que contiene el campo.
@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
Puede aumentarse para trabajar con instancias que no sean NIB, manejar valores predeterminados, etc., pero probablemente se haga una idea.
iOS está actuando un poco extraño cuando se trata de fuentes personalizadas. Intente eliminar "Ajustar para ajustar" para ese campo de texto. Si eso no funciona, supongo que lo que le molesta es el aumento de tamaño de la fuente.
Una solución simple para eso sería:
- (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]];
}
}
Tendrá que jugar un poco con el tamaño para que parezca que no hay cambios de tamaño al perder el foco en el UITextField
.
Si tiene un problema de espaciado importante entre caracteres como en la pregunta editada, la solución más simple (y un poco fea) sería crear una imagen de viñeta que coincida con el tamaño y espaciado anterior y coincida con la cantidad de caracteres ingresados por el usuario que lo hará aparece cuando el usuario abandona el UITextField
.
[passWordTextField resignFirstResponder];
passWordTextField.secureTextEntry = !passWordTextField.secureTextEntry;
[passWordTextField becomeFirstResponder];
¡Esta es la forma más rápida de resolver este error!