Сделать UITextField со статическим и атрибутивным префиксом

Я хотел бы сделать UITextField, который имеет статический префикс и который пользователь не может редактировать или удалять, который в то же время также имеет светло-серый цвет шрифта.

Редактируемая часть текстового поля всегда должна отображаться черным цветом.

Пример приведен ниже:

введите здесь описание изображения

По сути, он предназначен для ввода имени пользователя с постоянным префиксом домена.


Я уже пробовал использовать методы делегата textFieldShouldClear и textField:shouldChangeCharactersInRange:replacementString: вместе с NSMutableAttributedString, но просто не смог его взломать:

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

    [text addAttribute:NSForegroundColorAttributeName value:[UIColor grayColor] range:NSMakeRange(0, 7)];

    if (textField.text.length > 7)
    {    
        [text addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(7, textField.attributedText.length - 7)];
    }
    [text addAttribute:NSFontAttributeName value:[UIFont gothamFontForSize:textField.font.pointSize andWeight:kGothamLight] range:NSMakeRange(0, textField.attributedText.length)];


    return range.location > 6;
}

- (BOOL)textFieldShouldClear:(UITextField *)textField
{
    NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"kombit\\"];
    [text addAttribute:NSForegroundColorAttributeName value:[UIColor grayColor] range:NSMakeRange(0, 7)];
    [text addAttribute:NSFontAttributeName value:[UIFont gothamFontForSize:textField.font.pointSize andWeight:kGothamLight] range:NSMakeRange(0, text.length)];
    textField.attributedText = text;

    [textField setSelectedTextRange:[textField textRangeFromPosition:[textField endOfDocument] toPosition:[textField endOfDocument]]];

    return NO;
}

Я уверен, что кто-то уже делал что-то подобное.


person Zappel    schedule 20.08.2013    source источник
comment
I have already tried using... Покажите нам это, и мы найдем ошибки.   -  person James Webster    schedule 20.08.2013
comment
Надеюсь, вы сможете добавить UILabel в качестве leftView из UITextField, чтобы отобразить текст, который не редактируется.   -  person Dinesh Raja    schedule 20.08.2013


Ответы (2)


Приведенный ниже код создает строку с атрибутами из вашего постоянного текста, окрашивает ее в серый цвет и добавляет в текстовое поле. Затем в shouldChangeCharactersInRange: выполняется сравнение диапазонов, чтобы определить, находится ли диапазон в пределах области, которую должен занимать «kombit», и если это не так, атрибут черного цвета передается обратно в текстовое поле.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.textField setDelegate:self];

    NSString *fixedString = @"kombit\\";
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:fixedString];

    [attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor lightGrayColor] range:NSMakeRange(0, fixedString.length)];

    [self.textField setAttributedText:attributedString];
}

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSRange substringRange = [textField.text rangeOfString:@"kombit\\"];

    if (range.location >= substringRange.location && range.location < substringRange.location + substringRange.length) {
        return NO;
    }

    NSMutableAttributedString *attString = [textField.attributedText mutableCopy];

    [attString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(substringRange.length, textField.text.length - substringRange.length)];

    [textField setAttributedText:attString];

    return YES;
}

ИЗМЕНИТЬ:

Хорошо, я никогда не ожидал, что это будет такой большой проблемой, и, честно говоря, мне стыдно публиковать этот код, потому что он действительно грязный, но, похоже, он делает свою работу лучше, чем раньше.

В итоге я создал свойство для ссылки на BOOL, чтобы указать, должен ли текст обновляться (чтобы заблокировать рекурсию), и добавил цель к событию управления UIControlEventEditingChanged текстового поля, чтобы получить обратный вызов при редактировании.

Затем, поскольку по какой-то причине ни один из обычных способов сделать это здесь не работает, я перемещаю «курсор» в конец текстового поля, размещая вызов beFirstResponder сразу после вызова resignFirstResponder, и неожиданно это в значительной степени работает. Существует проблема с небольшим изменением размера текста, которую мне еще предстоит выявить, но это должно быть просто вопросом добавления дополнительных атрибутов, чтобы они соответствовали размеру шрифта, который вы хотите

Извините, я не мог больше помочь в решении этой проблемы, это довольно любопытная проблема. И я обычно ненавижу предлагать это, но, потратив столько времени на попытки сделать что-то, что должно быть тривиальным, я начинаю думать, что в NSAttributedString происходит что-то ошибочное. В любом случае, дайте мне знать, если этот код в конечном итоге приведет вас к ответу, я был бы очень заинтересован в решении.

@property (weak, nonatomic) IBOutlet UITextField *textField;
@property (nonatomic, assign) BOOL shouldUpdateAttributes;



- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.textField setDelegate:self];
    [self.textField setSpellCheckingType:UITextSpellCheckingTypeNo];
    [self setShouldUpdateAttributes:YES];


    NSString *fixedString = @"kombit\\ ";
    [self.textField setText:fixedString];

    [self.textField addTarget:self action:@selector(textFieldDidChangeText:) forControlEvents:UIControlEventEditingChanged];
    [self textFieldDidChangeText:self.textField];
}

- (void)textFieldDidChangeText:(UITextField *)sender
{
    if (self.shouldUpdateAttributes) {
        [self setShouldUpdateAttributes:NO];

        NSString *fixedString = @"kombit\\ ";

        NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:sender.text];

        [attributedString setAttributes:@{NSForegroundColorAttributeName: [UIColor lightGrayColor]} range:NSMakeRange(0, fixedString.length)];
        [attributedString setAttributes:@{NSForegroundColorAttributeName: [UIColor blackColor]} range:NSMakeRange(fixedString.length, sender.text.length - fixedString.length)];

        [sender setAttributedText:attributedString];
        [sender resignFirstResponder];
        [sender becomeFirstResponder];
    }
}


- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    [self setShouldUpdateAttributes:YES];
    NSString *fixedString = @"kombit\\";
    NSRange substringRange = [textField.text rangeOfString:fixedString];

    if (range.location >= substringRange.location && range.location < substringRange.location + substringRange.length) {
        return NO;
    }

    return YES;
}
person Mick MacCallum    schedule 20.08.2013
comment
Это очень близко к тому, что я пробовал. Однако, когда свойство attributedText установлено в методе textField: shouldChangeCharactersInRange:, «курсор» перемещается в начало текста. - person Zappel; 20.08.2013
comment
Нет у меня нет. Я только что попробовал со «свежим» текстовым полем - происходит то же самое. Может быть, вы поделитесь проектом Xcode? - person Zappel; 20.08.2013
comment
Спасибо! У меня тоже нормально работает под iOS 7, а не под iOS 6? - person Zappel; 20.08.2013
comment
Это было бы очень признательно! - person Zappel; 20.08.2013
comment
давайте продолжим обсуждение в чате - person Zappel; 21.08.2013

Поместите просто UILabel (стиль, как вы хотите) слева от UITextField и установите rect для текста UITextField's.

http://alwawee.com/wordpress/2013/02/18/uitextfield-edge-insets/

person Injectios    schedule 20.08.2013
comment
UITextField не имеет свойства contentInset. - person Zappel; 20.08.2013
comment
да, извините, это для UITextView, чтобы добиться этого для UITextField, вы должны создать подкласс UITextField alwawee.com/wordpress/2013/02/18/uitextfield-edge-insets - person Injectios; 20.08.2013
comment
Это решение является быстрым и грязным и приводит к неадекватному поведению: когда текстовое поле редактируется, метка всегда видна, что устраняет иллюзию простого префикса, который нельзя редактировать. - person Zappel; 20.08.2013