Выбор языка клавиатуры для UITextField с secureTextEntry - PullRequest
8 голосов
/ 26 июля 2011

Я застрял с проблемой изменения языка для поля пароля.В моем приложении мне нужно ввести логин / пароль на иврите, не заботясь о текущей локали.Когда я пытаюсь войти в систему, то все в порядке, я могу сменить клавиатуру на иврит и войти в систему.Но когда я пытаюсь ввести пароль в защищенном textField, клавиатура появляется без кнопки выбора языка, поэтому я могу вводить только английские буквы.

Дело в том, что логины / пароли могут быть на английском или на иврите.

Как поместить кнопку выбора языка в защищенное текстовое поле?

Ответы [ 3 ]

6 голосов
/ 28 июля 2011

Не нашел решения. Пришлось сделать этот фрагмент:

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
textField.text = [textField.text stringByReplacingCharactersInRange:range withString:string];

NSString *pass = password;
pass = [pass stringByReplacingCharactersInRange:range withString:string];

[password release];
password = nil;

password = [[NSString stringWithString:pass] retain];

[self hideTextInTextFieldExceptOne:string];

[self performSelector:@selector(hideTextInTextField) withObject:self afterDelay:1.0];

return NO;
}

- (void)hideTextInTextFieldExceptOne:(NSString *)string
{    
int lenght = [passwordTextField.text length];

for (int i = 0; i < lenght-1; i++)
{
    NSRange range = NSMakeRange(i, 1);
    passwordTextField.text = [passwordTextField.text stringByReplacingCharactersInRange:range withString:@"*"];
}
}

- (void)hideTextInTextField
{
NSUInteger lenght = [passwordTextField.text length];
passwordTextField.text = @"";

for (int i = 0; i < lenght; i++)
{
    passwordTextField.text = [passwordTextField.text stringByAppendingString:@"*"];
}
}
1 голос
/ 01 июня 2014

К сожалению, опубликованное здесь решение не работает для языков с составными символами (например, корейского).

Такие языки, как корейский (хангул), имеют составной символ, в котором каждая буква состоит из нескольких символов. Например, ‘ㅁ’, ‘ㅏ’ и ‘ㄴ’ - все отдельные символы, но при объединении они становятся ‘만’, который рассматривается как одна буква.

Вот решение, которое работает для всех языков.

Поместите UILabel поверх UITextField. Установите рамку UILabel немного меньше, чем UITextField, чтобы она находилась внутри UITextField, но все еще затеняет текст UITextField. TextField: shouldChangeCharactersInRange: withReplacementString вызывается до завершения текста. Это означает, что нам нужно завершить текст самостоятельно. Это сложнее сделать с составными символьными языками, такими как корейский. Вместо этого зарегистрируйтесь для UITextFieldTextDidChangeNotification, которая будет вызываться после появления нового текста в UITextField.

@interface MKSecureTextField()<UITextFieldDelegate>
@property (nonatomic, strong) UITextField* textField;
@property (nonatomic, strong) UILabel* hideLabel;
@property (nonatomic, strong) NSTimer* hideTimer;
@property (nonatomic, strong) NSTimer* blinkTimer;
@end

@implementation MKSecureTextField


- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        self.textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
        _textField.userInteractionEnabled = YES;
        _textField.borderStyle = UITextBorderStyleRoundedRect;
        _textField.font = [UIFont systemFontOfSize:14];
        _textField.placeholder = @"enter text";
        _textField.autocorrectionType = UITextAutocorrectionTypeNo;
        _textField.keyboardType = UIKeyboardTypeDefault;
        _textField.returnKeyType = UIReturnKeyDone;
        _textField.clearButtonMode = UITextFieldViewModeWhileEditing;
        _textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
        _textField.delegate = self;

        self.hideLabel = [[UILabel alloc] initWithFrame:CGRectMake(6, 5, frame.size.width-10, frame.size.height-12)];
        _hideLabel.backgroundColor = [UIColor whiteColor];


        [self addSubview:_textField];
        [self addSubview:_hideLabel];

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldDidChange:) name:UITextFieldTextDidChangeNotification object:nil];

    }
    return self;
}

Когда получено UITextFieldTextDidChangeNotification, скрыть все, кроме последнего символа. Скрытый текст будет программно установлен на UILabel. Также запланируйте таймер, который будет скрывать последний символ. Этот таймер становится недействительным, если набрано больше текста.

- (void)textFieldDidChange:(NSNotification*)notification
{
    UITextField* textField = notification.object;
    if (textField == _textField)
    {
        NSString* text = textField.text;


        [self hideExceptLastCharacter:text];

        [self.hideTimer invalidate];
        self.hideTimer = [NSTimer scheduledTimerWithTimeInterval:1
                                                          target:self
                                                              selector:@selector(hideLastCharacter)
                                                    userInfo:nil
                                                     repeats:NO];


    }
}

У UILabel нет мигающего курсора. Таким образом, мы подражаем ему, чередуя '|' и пробел. Мигающий курсор помещается, когда редактирование начинается, и удаляется, когда редактирование заканчивается.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    if (_hideLabel.text == nil)
    {
        _hideLabel.text =  @"|";
    }
    else
    {
        _hideLabel.text =  [_hideLabel.text stringByAppendingString:@"|"];
    }

    self.blinkTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(blinkCursor) userInfo:nil repeats:YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    NSRange range;

    range.location = _hideLabel.text.length - 1;
    range.length = 1;

    _hideLabel.text = [_hideLabel.text stringByReplacingCharactersInRange:range withString:@""];

    [_blinkTimer invalidate];
}

- (void)blinkCursor
{
    if (_hideLabel.text.length > 0)
    {
        static BOOL visible = YES;

        NSRange range;
        range.location = _hideLabel.text.length - 1;
        range.length = 1;

        if (visible)
        {
            _hideLabel.text = [_hideLabel.text stringByReplacingCharactersInRange:range withString:@" "];
        }
        else
        {
            _hideLabel.text = [_hideLabel.text stringByReplacingCharactersInRange:range withString:@"|"];
        }
        visible = !visible;
    }
}

Персонажи, кроме последнего, скрыты. Это установлено на UILabel. UITextField остается нетронутым.

- (void)hideExceptLastCharacter:(NSString*)string
{
    int length = [_textField.text length];

    NSString* s = @"";
    for (int i = 0; i < length-1; i++)
    {
        s = [s stringByAppendingString:@"●"];
    }

    if (_textField.text.length > 0)
    {
        _hideLabel.text = [s stringByAppendingString:[_textField.text substringFromIndex:_textField.text.length-1]];
        _hideLabel.text = [_hideLabel.text stringByAppendingString:@"|"];
    }
    else
    {
        _hideLabel.text = @"|";
    }
}

- (void)hideLastCharacter
{
    if (_hideLabel.text.length > 1)
    {
        NSRange range;
        range.location = [_hideLabel.text length]-2;
        range.length = 1;

        _hideLabel.text = [_hideLabel.text stringByReplacingCharactersInRange:range withString:@"●"];
    }
}

- (void)dealloc
{
    [_hideTimer invalidate];
    [_blinkTimer invalidate];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end

См. Проект Github для справки.

1 голос
/ 11 декабря 2012

Оптимизированный ответ @lonlywolf для улучшения производительности кода: Оптимизированы только два метода, где есть циклы, которые замедляют программу при наборе более 30 символов

- (void)hideTextInTextFieldExceptOne:(NSString *)string
{
    int lenght = [passwordTextField.text length];
    if (lenght -1 > 0) {
        NSString *resultString = @"";
        for (int i = 0; i < lenght-1; i++)
        {
            resultString = [resultString stringByAppendingFormat:@"*"];
        }
        NSRange range = NSMakeRange(0, lenght - 1);
        passwordTextField.text = [fieldPassword.text stringByReplacingCharactersInRange:range withString:resultString];
    }
}

- (void)hideTextInTextField
{
    int lenght = [passwordTextField.text length];
    if (lenght > 0) {
        NSString *resultString = @"";
        for (int i = 0; i < lenght; i++)
        {
            resultString = [resultString stringByAppendingFormat:@"*"];
        }
        passwordTextField.text = resultString;
    }
}
...