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

Как увеличить ширину текстового поля в соответствии с введенным текстом?

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

Я ограничил текстовое поле и кнопку так, чтобы текстовое поле было сосредоточено на экране, а кнопка рядом с ним. (Текстовое поле должно быть доступно для редактирования, кнопка должна быть нажата)

Размер текстового поля:

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

Когда я ввожу текст в него, размер должен автоматически увеличиваться:

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

Как я могу это достичь?

4b9b3361

Ответ 1

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

 func getWidth(text: String) -> CGFloat
{
    let txtField = UITextField(frame: .zero)
    txtField.text = text
    txtField.sizeToFit()
    return txtField.frame.size.width
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
    let width = getWidth(textField.text!)
    if UIScreen.mainScreen().bounds.width - 55 > width
    {
        txtWidthOfName.constant = 0.0
        if width > txtWidthOfName.constant
        {
            txtWidthOfName.constant = width
        }
        self.view.layoutIfNeeded()
    }
    return true
}

Версия Objective C

-(CGFloat)getWidth:(NSString *)text{
    UITextField * textField = [[UITextField alloc]initWithFrame:CGRectZero];
    textField.text = text;
    [textField sizeToFit];
    return textField.frame.size.width;
}

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (self.textFieldName.isEditing == YES) {
        CGFloat width = [self getWidth:textField.text];
        if ([UIScreen mainScreen].bounds.size.width - 60 > width) {
            self.txtWidthOfName.constant = 0.0;
            if (width > self.txtWidthOfName.constant) {
                self.txtWidthOfName.constant = width;
            }
            [self.view layoutIfNeeded];
        }
    }
    return YES;
}

Ответ 2

Обманным обходным путем для получения ширины для конкретной строки будет

func getWidth(text: String) -> CGFloat {
    let txtField = UITextField(frame: .zero)
    txtField.text = text
    txtField.sizeToFit()
    return txtField.frame.size.width
}

И чтобы получить ширину,

let width = getWidth(text: "Hello world")
txtField.frame.size.width = width
self.view.layoutIfNeeded() // if you use Auto layout

Если у вас есть ограничение, связанное с шириной txtField, сделайте

yourTxtFieldWidthConstraint.constant = width
self.view.layoutIfNeeded() // if you use Auto layout

Edit Мы создаем UITextField с фреймом в основном всех нулей. Когда вы вызываете sizeToFit(), он устанавливает кадр UITextField таким образом, чтобы он отображал все его содержимое буквально без лишних пробелов вокруг него. Мы только хотели его ширину, поэтому я вернул ширину только что созданного UITextField. ARC позаботится о том, чтобы удалить его из памяти для нас.

Обновление

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

        if textField.text != nil {
            let text = textField.text! as NSString
            let finalString = text.replacingCharacters(in: range, with: string)
            textField.frame.size.width = getWidth(text: finalString)
        }

        return true
    }

Ответ 3

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

Вот пример в Swift 3

class Test: UITextField {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupTextChangeNotification()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupTextChangeNotification()
    }

    func setupTextChangeNotification() {
        NotificationCenter.default.addObserver(
            forName: Notification.Name.UITextFieldTextDidChange,
            object: self,
            queue: nil) { (notification) in
                UIView.animate(withDuration: 0.05, animations: {
                    self.invalidateIntrinsicContentSize()
                })
        }
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    override var intrinsicContentSize: CGSize {
        if isEditing {
            if let text = text,
                !text.isEmpty {
                // Convert to NSString to use size(attributes:)
                let string = text as NSString
                // Calculate size for current text
                var size = string.size(attributes: typingAttributes)
                // Add margin to calculated size
                size.width += 10
                return size
            } else {
                // You can return some custom size in case of empty string
                return super.intrinsicContentSize
            }
        } else {
            return super.intrinsicContentSize
        }
    }
}

Ответ 4

Внедрить следующий метод UITextFieldDelegate. Используйте подход, предоставленный Мэттом, чтобы получить требуемую ширину textField. В автоматическом макете убедитесь, что у вас установлены ограничения по центру и ширине для текстового поля. Создайте IBOutlet для ограничения ширины в файле кода. Также убедитесь, что вы задали свойство delegate вашего текстового поля

@IBOutlet weak var widthConstraint: NSLayoutConstraint!

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
     let width = getWidth(text : textField.text)
     if width > widthConstraint.constant {
         widthConstraint.constant = width
     }
     self.layoutIfNeeded() 
     return true
}

Ответ 5

Я думаю, что это лучшее решение, чем ограничение ширины, которое вы должны изменить:

Измените размер UITextField при наборе текста (используя Autolayout)

- (IBAction) textFieldDidChange: (UITextField*) textField
{
    [UIView animateWithDuration:0.1 animations:^{
        [textField invalidateIntrinsicContentSize];
    }];
}

При желании вы можете опустить анимацию.

EDIT: здесь пример проекта: https://github.com/TomSwift/growingTextField

Ответ 6

Ответы всем требуют кучу кода, но вы можете делать все построители интерфейса; не требуется код.

Просто вставьте textField в UIStackView и ограничьте, чтобы stackView был меньше или равен его супервизору минус некоторая константа (если вы хотите, вы также можете дать ему минимальную ширину). Стек стек будет заботиться о том, чтобы сделать textField своим внутренним размером или максимальной шириной stackView (которая когда-либо меньше), так как вы вводите изменения размера автоматически, чтобы соответствовать контенту.

Ответ 7

Кажется настолько разочаровывающим, что нет прямого способа, как есть "Autoshrink" для "Минимального размера шрифта" для UILabel в самой IB. "Настроить для подгонки" в IB для текстового поля тоже нехорошо.

Почему Apple заставляет нас писать весь этот шаблонный код, когда текстовому полю требуется Autoshrink, если не больше, чем UILabel!

Ответ 8

Мы можем легко сделать это, установив ограничения UITextField следующим образом:

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

//Проверено на Xcode 9.1, Swift 4

Вывод:

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