Подтвердить что ты не робот

Как достичь этого текста заполнителя исчезает символ по символу в UITextField

Не могли бы вы помочь мне.

В UITextField, когда мы предоставляем текст заполнителя, его строка-заполнитель исчезнет, ​​когда мы введем какой-либо символ. Как я могу достичь того, что только введенный символ будет не полным? Это означает, что если я напечатаю 3 символа, будут удалены только первые 3 символа заполнителя.

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

#EDIT 1

Кроме того, новый цвет текста вводится, а другой оставшийся цвет текста символа остается таким же.

Спасибо заранее.

4b9b3361

Ответ 1

Я не верю, что поведение по умолчанию для замещающего объекта редактируется, но то, что вы пытаетесь выполнить, может быть выполнено с помощью NSAttributedString для имитации значения placeholder.

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

Пользовательское текстовое поле заполнителя

import UIKit

class CustomPlaceholderTextFieldHandler: NSObject {
    let placeholderText: String
    let placeholderAttributes = [NSForegroundColorAttributeName : UIColor.lightGray]
    let inputAttributes = [NSForegroundColorAttributeName : UIColor(red: 255/255, green: 153/255, blue: 0, alpha: 1.0)]
    var input = ""

    init(placeholder: String) {
        self.placeholderText = placeholder
        super.init()
    }

    func resetPlaceholder(for textField: UITextField) {
        input = ""
        setCombinedText(for: textField)
    }

    fileprivate func setCursorPosition(for textField: UITextField) {
        guard let cursorPosition = textField.position(from: textField.beginningOfDocument, offset: input.characters.count)
            else { return }

        textField.selectedTextRange = textField.textRange(from: cursorPosition, to: cursorPosition)
    }

    fileprivate func setCombinedText(for textField: UITextField) {
        let placeholderSubstring = placeholderText.substring(from: input.endIndex)
        let attributedString = NSMutableAttributedString(string: input + placeholderSubstring, attributes: placeholderAttributes)
        attributedString.addAttributes(inputAttributes, range: NSMakeRange(0, input.characters.count))
        textField.attributedText = attributedString
    }
}

extension CustomPlaceholderTextFieldHandler: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        if string == "" {
            if input.characters.count > 0 {
                input = input.substring(to: input.index(before: input.endIndex))
            }
        } else {
            input += string
        }

        if input.characters.count <= placeholderText.characters.count {
            setCombinedText(for: textField)
            setCursorPosition(for: textField)
            return false
        }
        return true
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {
        setCursorPosition(for: textField)
    }
}

Здесь я инициализировал gif выше:

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!
    let placeholderHandler = CustomPlaceholderTextFieldHandler(placeholder: "_2_-__-__A")

    override func viewDidLoad() {
        super.viewDidLoad()
        textField.delegate = placeholderHandler
        placeholderHandler.resetPlaceholder(for: textField)
    }
}

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

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

Ответ 2

Вместо использования текста заполнителя используйте UILabel ниже вашего текстового поля и дайте тот же стиль шрифта обоим. текст ярлыка должен быть как "- - - - -"

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

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if textField.text?.characters.count == 0 && string.characters.count != 0 {
        textField.text = textField.text! + " "
    }
     else {
        return false
    }

    if textField.text?.characters.count == 1 && string.characters.count != 0 {
        textField.text = textField.text! + " "
    }
    else {
        return false
    }

    if textField.text?.characters.count == 2 && string.characters.count != 0 {
        textField.text = textField.text! + " "
    }
    else {
        return false
    }
    if textField.text?.characters.count == 3 && string.characters.count != 0 {
        textField.text = textField.text! + " "
    }
    else {
        return false
    }

    return true
}

Ответ 3

Есть мое решение с использованием свойства текста UITextField

+(BOOL)shouldChangeCharactersInRange:(NSRange)range
                   replacementString:(NSString *)string
                           textField:(UITextField *)textField
                                mask:(NSString *)mask withMaskTemplate:(NSString *)maskTemplate{

    NSString * alreadyExistString = @"";
    if (string.length == 0) {
        alreadyExistString = textField.text;
        for (int i = range.location; i >= 0; i--) {
            unichar  currentCharMask = [maskTemplate characterAtIndex:i];
            unichar  currentChar = [alreadyExistString characterAtIndex:i];
            if (currentCharMask == currentChar) {// fixed value and _
                continue;
            }else{
                alreadyExistString = [alreadyExistString stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:@"_"];
                break;
            }
        }
        textField.text = alreadyExistString;
        return NO;
    }else{
        alreadyExistString = [textField.text stringByReplacingCharactersInRange:NSMakeRange(range.location, 1) withString:string];
    }

    NSMutableString * validText = [[NSMutableString alloc] init];

    int last = 0;
    BOOL append = NO;
    for (int i = 0; i < alreadyExistString.length; i++) {
        unichar  currentCharMask = [mask characterAtIndex:i];
        unichar  currentChar = [alreadyExistString characterAtIndex:i];
        BOOL isLetter = [[NSCharacterSet alphanumericCharacterSet] characterIsMember: currentChar];
        BOOL isDigit  = [[NSCharacterSet decimalDigitCharacterSet] characterIsMember: currentChar];
        if ((isLetter && currentCharMask == '#') || (isDigit && currentCharMask == '9')) {
            [validText appendString:[NSString stringWithFormat:@"%c",currentChar]];
        }else{
            if (currentCharMask == '#' || currentCharMask == '9') {
                break;
            }
            if ((isLetter && currentCharMask!= currentChar)|| (isDigit && currentCharMask!= currentChar)) {
                append = YES;
            }
            [validText appendString:[NSString stringWithFormat:@"%c",currentCharMask]];
        }
        last = i;
    }

    for (int i = last+1; i < mask.length; i++) {
        unichar currentCharMask = [mask characterAtIndex:i];
        if (currentCharMask != '#' && currentCharMask != '9') {
            [validText appendString:[NSString stringWithFormat:@"%c",currentCharMask]];
        }
        if (currentCharMask == '#' || currentCharMask == '9') {
            break;
        }
    }
    if (append) {
        [validText appendString:string];
    }

    NSString *placeHolderMask = textField.text;
    NSString *sub = [validText substringWithRange:NSMakeRange(range.location, 1)];
    placeHolderMask = [placeHolderMask stringByReplacingCharactersInRange:NSMakeRange(range.location, 1) withString:sub];
    textField.text = placeHolderMask;
    return NO;
}

@property (nonatomic,strong) NSString * maskTemplate;// like: _2_-__-__A
@property (nonatomic,strong) NSString * mask;// like: #2#-99-##A
  • Первоначально заданный текст текстового поля для маскирования шаблона
  • Затем, когда пользователь вводит вход, должен активироватьChangeCharactersInRange и выполняет отличную работу

#Edit 1 Существует также еще один код, который я выполнил, который перемещает курсор в позицию подчеркивания. Если кому-то нужна помощь. Прошу прокомментировать, я помогу вам.

#Edit 2

Проблемы, с которыми я столкнулся, используя этот подход

  • Невозможно изменить цвет отдельного текста. Цвет будет таким же для строки, как и для подчеркивания @ "_", и символы ввода имеют один и тот же цвет.
  • Если пользователь не предоставляет никаких входных данных, я должен предоставить чек для отправки пустого в виде строки.
  • Отслеживание отдельных входов.

Спасибо, Все еще ожидаем, если будет какое-либо другое обходное решение с использованием String String.

Ответ 4

Я думаю, это именно то, что вы ищете. Создайте свой объект UITextField с текстом _2_-__-__A (не текст заполнителя). Затем используйте его контроллер представления в качестве делегата и добавьте его в контроллер вида:

-(BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString*)string{
    if (range.length>1) return NO; // Avoids removing multiple characters at once
    if (range.location==1) range.location++;  // '2' index
    if (range.location==3) range.location++;  // '-' index
    if (range.location==6) range.location++;  // '-' index
    if (range.location==9)  return NO; // 'A' index
    if (range.location==10) return NO; // String end
    if ([string isEqualToString:@""]) return NO; //Avoids removing characters

    if (range.length==0) {
        range.length++;
        UITextPosition *beginning = textField.beginningOfDocument;
        UITextPosition *start = [textField positionFromPosition:beginning offset:range.location];
        UITextPosition *end = [textField positionFromPosition:start offset:range.length];
        UITextRange *textRange = [textField textRangeFromPosition:start toPosition:end];
        [textField setSelectedTextRange:textRange];
    }

    return YES;
}
-(void)textFieldDidBeginEditing:(UITextField*)textField{
    UITextPosition *beginning = textField.beginningOfDocument;
    UITextPosition *start = [textField positionFromPosition:beginning offset:0];
    UITextPosition *end = [textField positionFromPosition:start offset:0];
    UITextRange *textRange = [textField textRangeFromPosition:start toPosition:end];
    [textField setSelectedTextRange:textRange];
}
-(BOOL)textFieldShouldReturn:(UITextField*)textField{
    [passwordInput resignFirstResponder];
    return YES;
}

Он должен работать по назначению.

Ответ 5

Для этой ситуации используйте атрибутную строку в swift, например, ниже,

let attributeFontSaySomething : [String : Any] = [NSFontAttributeName : UIFont.systemFont(ofSize: 12.0)]
let attributeColorSaySomething : [String : Any] = [NSForegroundColorAttributeName : UIColor.blue]

var attributes = attributeFontSaySomething
for (key, value) in attributeColorSaySomething {
    attributes(value, forKey: key)
}

let attStringSaySomething = NSAttributedString(string: "Say something", attributes: attributes)

Ответ 6

Нет. Вы не можете сделать это, не создавая настраиваемый слой в поле UIText после того, как вы должны проверить, что введенный char соответствует строке placehoder, и только этот charecter будет заменен. см. также Замена символа после каждого типа в UITextField?