如何根据input的文本增加文本字段的宽度?
我需要根据其内容增加文本字段的宽度。 当用户input文本时,文本字段大小应该自动增加。 我有一个closures(X)button旁边的文本字段。
我限制了文本字段和button,使文本字段居中在屏幕上,并且button与其相邻。 (文本字段应该是可编辑的,button应该是可点击的)
文本字段大小是这样的:
当我input文字时,尺寸应该会自动增加:
我怎样才能做到这一点?
我解决了我的问题:使用这个文本字段不在屏幕之外。
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; }
一个厚脸皮的解决方法,以获得一个特定的string的宽度将是
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
编辑我们正在创build一个基本上全零的框架的UITextField。 当你调用sizeToFit()的时候,它会设置UITextField的框架,使其显示它的所有内容,并且没有多余的空格。 我们只想要它的宽度,所以我返回了新创build的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 }
你可以通过重写UITextField
类来实现它,并返回intrinsicContentSize
自定义值。 此外,您还需要订阅文本更改事件,并在文本更改animation时使内容内容大小无效
这里是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 } } }
实现UITextFieldDelegate
以下方法。 使用由Matt提供的方法来获得所需的textField的宽度。 在自动布局中,确保您已经为textfield设置了中心和宽度约束。 在代码文件中为您的宽度约束创buildIBOutlet。 另外请确保你设置了你的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 }
我认为这是一个更好的解决scheme,而不是有一个宽度约束,你必须修改:
在input时调整UITextField的大小(使用Autolayout)
- (IBAction) textFieldDidChange: (UITextField*) textField { [UIView animateWithDuration:0.1 animations:^{ [textField invalidateIntrinsicContentSize]; }]; }
如果需要,可以省略animation。
编辑 :这是一个示例项目: https : //github.com/TomSwift/growingTextField
答案都需要一堆代码,但你可以做所有的界面生成器; 没有需要的代码。
只要将textFieldembedded到UIStackView中,并将stackView限制为小于或等于其superview减去一些常数(如果你想要,也可以给它一个最小宽度)。 stackView会照顾到textField的固有尺寸,或者是stackView的最大宽度(这个尺寸越小越好),所以你可以自动input尺寸的大小来适应内容。
似乎很令人沮丧的是,没有直接的方式,像IB自己的UILabel
有“Autoshrink”到“Minimum Font size”。 IB中的“调整为适合”文本字段也不好。
为什么苹果让我们编写所有这些样板代码,当文本字段需要Autoshrink时,如果不超过UILabel的话!