如何根据打字文本增加文本字段的宽度?

时间:2017-01-03 05:03:28

标签: ios swift autolayout uitextfield

我需要根据文本字段的内容增加文本字段的宽度。当用户输入文本时,文本字段大小应自动增加。我在这个文本字段旁边有一个关闭(X)按钮。

我已经约束了文本字段和按钮,以便文本字段在屏幕上居中,并且按钮与它相邻。 (文本字段应该是可编辑的,按钮应该是可点击的)

文本字段大小为:

enter image description here

当我在其中输入文字时,尺寸应自动增加:

enter image description here

我怎样才能做到这一点?

8 个答案:

答案 0 :(得分:11)

我解决了我的问题:将此文本字段用于不在屏幕之外。

 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
}

目标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;
}

答案 1 :(得分:11)

您可以通过覆盖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
        }
    }
}

答案 2 :(得分:7)

获取特定字符串宽度的厚颜无耻的解决方法是

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

修改 我们正在创建一个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 :(得分:3)

实施UITextFieldDelegate的以下方法。使用Matt提供的方法获得textField所需的宽度。在自动布局中,请确保为文本字段设置了中心和宽度约束。在代码文件中为宽度约束创建IBOutlet。还要确保设置textField的委托属性

@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
}

答案 4 :(得分:3)

答案都需要一堆代码,但你可以做一切界面构建器;无需代码。

只需将textField嵌入到UIStackView中,并将stackView限制为小于或等于其superview减去某个常量(如果你想要,你也可以给它一个最小宽度)。 stackView将始终使textField成为其固有大小,或者stackView的最大宽度(通常更小),因此当您自动键入大小更改以适应内容时。

答案 5 :(得分:3)

我认为这是一个比你必须修改的宽度约束更好的解决方案:

Resize a UITextField while typing (by using Autolayout)

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

如果需要,您可以省略动画..

编辑:这是一个示例项目:https://github.com/TomSwift/growingTextField

答案 6 :(得分:2)

我们可以通过设置UITextField约束来轻松实现:

enter image description here

//在Xcode 9.1,Swift 4上测试

输出:

enter image description here

答案 7 :(得分:0)

似乎非常令人沮丧,因为没有像#34; Autoshrink&#34;到&#34;最小字体大小&#34;对于IB本身的UILabel。 &#34;调整适合&#34;在IB中,文本字段也不好。

为什么Apple让我们编写所有这些样板代码,当文本字段需要自动收缩时,如果不超过UILabel那么多!