How to increase width of textfield according to typed text?
I need to increase a text field's width according to its content. When the user inputs text, then the textfield size should increase automatically. I have one close (X) button next to this text field.
I have constrained the text field and button so that the text field is centered on screen, and the button is adjacent to it. (Text field should be editable, button should be clickable)
Text field size is this:
When I enter text in it, the size should automatically increase:
How can I achieve this?
-
Check this out stackoverflow.com/questions/37355212/… – Vishnu gondlekar Jan 3 '17 at 5:10
-
How to calculate the width of text ? that i typing – Mitesh jadav Jan 3 '17 at 5:12
-
Check this stackoverflow.com/questions/30450434/… – Vishnu gondlekar Jan 3 '17 at 5:13
-
I cant not understand in this answer , how i give autolayout first time in my textfield . – Mitesh jadav Jan 3 '17 at 5:14
-
With auto layout it is not possible – Vishnu gondlekar Jan 3 '17 at 5:15
I solve my problem : use this for textfield not go outside of 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;
}
You can achieve it with overriding UITextField class and return custom value in intrinsicContentSize. Also you need to subscribe to text change event and invalidate intrinsic content size on text change animated
Here is 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
}
}
}
A cheeky workaround to get width for a particular string 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 a constraint linked to txtField's width then do
yourTxtFieldWidthConstraint.constant = width
self.view.layoutIfNeeded() // if you use Auto layout
Edit We are creating a UITextField with a frame of basically all zeros. When you call sizeToFit(), it will set the frame of UITextField in a way that it will show all of its content with literally no extra spaces around it. We only wanted its width, so I returned the width of the newly created UITextField. ARC will take care of removing 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
}
-
can you explain please when i Write this code – Mitesh jadav Jan 3 '17 at 5:39
-
I write this function , but not understand , where write this yourTxtFieldWidthConstraint.constant = width self.layoutIfNeeded() // if you use Auto layout – Mitesh jadav Jan 3 '17 at 5:56
-
That's your outlet to width constraint. Do it in 'shouldChangeCharacterInRange' text field delegate – Matt Jan 3 '17 at 5:57
-
but i write any text in textfield , that auto increase – Mitesh jadav Jan 3 '17 at 5:58
-
self.layoutIfNeeded() give me an error – Mitesh jadav Jan 3 '17 at 5:59
Implement following method of UITextFieldDelegate. Use approach provided by Matt to get required width of textField. In auto layout make sure you have centre and width constraints set for textfield. Create IBOutlet for your width constraint in code file. Also make sure you set delegate property of your 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
}
-
1self.layoutIfNeeded() give me an error – Mitesh jadav Jan 3 '17 at 5:53
-
Do self.view.layoutIfNeeded() in that case – Vishnu gondlekar Jan 3 '17 at 5:54
-
Thank you for help – Mitesh jadav Jan 3 '17 at 6:03
I think this is a better solution than having a width constraint that you have to modify:
Resize a UITextField while typing (by using Autolayout)
- (IBAction) textFieldDidChange: (UITextField*) textField
{
[UIView animateWithDuration:0.1 animations:^{
[textField invalidateIntrinsicContentSize];
}];
}
You can omit the animation if desired..
EDIT: Here's an example project: https://github.com/TomSwift/growingTextField
-
Except it doesn't work... – Learn OpenGL ES Apr 19 '17 at 20:15
-
@LearnOpenGLES check that you're handling the UIControlEventEditingChanged and that your handler is being called with each keyboard keypress. Also check that your UITextField isn't constrained in width. – TomSwift Apr 21 '17 at 18:31
-
Thanks for replying with the extra info. I checked and the handler is being called on each keypress, but nothing changes until after editing is complete, which is also the default behavior. The only solution that I've seen work is one that overrides the actual UITextField class. Do you have a working demo I could test? – Learn OpenGL ES Apr 24 '17 at 18:08
-
@LearnOpenGLES - see github.com/TomSwift/growingTextField – TomSwift Apr 25 '17 at 22:30
-
Confirmed that the sample project works for me, though unfortunately the solution doesn't, not even with the same event. I don't believe that the field is constrained in width as it's still able to grow and push aside other views, but my layout is also more complex so hard to say for sure. In my case I also have to override the intrinsic content size: stackoverflow.com/a/43622411/1317564 You get an upvote from me as the answer does work, just not in some cases for some reason. – Learn OpenGL ES Apr 25 '17 at 23:28
The answers all require a bunch of code, but you can do everything interface builder; no code needed.
Just embed the textField in a UIStackView and constrain the stackView to be less than or equal to its superview minus some constant (if you want you can also give it a minimum width). The stackView will take care of always making the textField its intrinsic size, or the maxwidth of the stackView (which ever is smaller), so as you type the size changes automatically to fit the content.
-
This should be the accepted answer. – francis lanthier Sep 15 '17 at 19:34
Seems so frustrating that there is no direct way like there is "Autoshrink" to "Minimum Font size" for UILabel in IB itself. The "Adjust to Fit" in IB for a textfield is no good too.
Why does Apple make us write all this boilerplate code, when a text field needs Autoshrink as much if not more than the UILabel!





浙公网安备 33010602011771号