How to increase the width of the text field in accordance with the entered text?

I need to increase the width of the text box according to its contents. When the user enters text, the size of the text field should increase automatically. I have one close (X) button next to this text box.

I limited the text box and the button so that the text box is focused on the screen, and the button is next to it. (The text field should be editable, the button should be pressed)

Text Box Size:

enter image description here

When I enter text into it, the size should automatically increase:

enter image description here

How can i achieve this?

+20
ios uitextfield autolayout swift
Jan 03 '17 at 5:03 on
source share
8 answers

I solve my problem: use this for a text field, without going beyond the screen.

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 Version

 -(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; } 
+13
Jan 05 '17 at 7:25
source share

A tricky workaround to get the width for a particular row would be

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

And to get the width,

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

If you have txtField width constraint do

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

Edit We create a UITextField with a frame of basically all zeros. When you call sizeToFit (), it sets the UITextField frame so that it displays all its contents with literally no extra spaces around it. We just wanted its width, so I returned the width of the newly created UITextField. ARC will take care to remove it from memory for us.

Update

 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 } 
+7
Jan 03 '17 at 5:25
source share

You can achieve this with an override of the UITextField class and return a custom value in intrinsicContentSize . You also need to subscribe to the text change event and invalidate the own size of the content when the text changes animatedly.

Here is an example in 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 } } } 
+7
Jan 10 '17 at 23:23
source share

Implement the following UITextFieldDelegate method. Use the approach provided by Matt to get the required width of the textField. In the automatic layout, make sure that you have limits on the center and width for the text field. Create an IBOutlet to limit the width in the code file. Also make sure that you set the delegate property of your text field

 @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 } 
+3
Jan 03 '17 at 5:47 on
source share

I think this is a better solution than the width limit you should change:

Resize UITextField when typing (using Autolayout)

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

You can optionally omit the animation.

EDIT : here's a sample project: https://github.com/TomSwift/growingTextField

+3
Jan 11 '17 at 22:49
source share

Answers all require a bunch of code, but you can do all the interface builders; no code required.

Just insert a textField into the UIStackView and restrict the stackView to be less than or equal to its supervisor minus some constant (if you want, you can also give it a minimum width). The stack stack will take care of making textField its internal size or the maximum width of the stackView (which is ever smaller), as you enter resizing automatically to fit the content.

+1
Jan 11 '17 at 7:03 on
source share

It seems so disappointing that there is no direct way, as there is "Autoshrink" for the "Minimum font size" for UILabel in IB itself. "Customize to fit" in IB for the text box is also not good.

Why does Apple make us write all this boilerplate code when a text field requires Autoshrink, if not more than UILabel!

0
Jan 11 '17 at 6:43 on
source share

We can easily do this by setting the UITextField restrictions as follows:

enter image description here

// Tested on Xcode 9.1, Swift 4

Output:

enter image description here

0
Jan 09 '18 at 6:40
source share