Как достичь этого текста заполнителя исчезает символ по символу в UITextField
Не могли бы вы помочь мне.
В UITextField
, когда мы предоставляем текст заполнителя, его строка-заполнитель исчезнет, когда мы введем какой-либо символ. Как я могу достичь того, что только введенный символ будет не полным? Это означает, что если я напечатаю 3 символа, будут удалены только первые 3 символа заполнителя.
![введите описание изображения здесь]()
#EDIT 1
Кроме того, новый цвет текста вводится, а другой оставшийся цвет текста символа остается таким же.
Спасибо заранее.
Ответы
Ответ 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?