【问题标题】:UITextField placeholder text: adjust to fitUITextField 占位符文本:调整以适应
【发布时间】:2016-02-21 17:08:18
【问题描述】:

我将 UITextField 中的较长文本设置为占位符。我想要的是这个 placeholder text 在字段宽度太小时调整其字体大小。

我已经尝试过其他帖子中描述的这个解决方案(以编程方式和在 IB 中)

self.fieldTest.adjustsFontSizeToFitWidth = true
self.fieldTest.minimumFontSize = 10.0

我在这里错过了什么?

【问题讨论】:

  • 只是尝试检测设备并根据该调整文本字段占位符。希望这会对您有所帮助。
  • 也许that 可以提供帮助。
  • 你能分享使用fieldTest对象的代码吗?也许我们可以从那里找到缺少的东西
  • 什么是self.fieldTest?是文本字段出口吗?

标签: ios swift uitextfield


【解决方案1】:

试试这个:它工作正常,没有任何问题:

yourTextField.placeholder = "Adjust placeHolder text for textFields iOS"
let label = yourTextField.value(forKey: "_placeholderLabel") as? UILabel
label?.adjustsFontSizeToFitWidth = true

【讨论】:

    【解决方案2】:

    我的解决方案:

    if let label = yourTextField.value(forKey: "placeholderLabel") as? UILabel {
       label.adjustsFontSizeToFitWidth = true
    }
    

    别忘了这一点:

    yourTextField.minimumFontSize = 10 // 10 is an example, pass your minimumFontSize
    

    经过测试并完美运行。

    【讨论】:

      【解决方案3】:

      查看 UITextField 的类参考后,似乎 adjustsFontSizeToFitWidth 仅影响 UITextField 的 text 属性,而不影响 placeholder 属性。虽然我不知道如何让占位符响应adjustsFontSizeToFitWidth,但我可以提出两个可能给你想要的外观的hacky想法。请注意,我现在不在 Mac 附近,所以我没有测试这些想法:

      1:
      由于占位符只是具有 70% 灰色的文本,因此您可以将标签的 text 属性设置为您需要的任何内容,然后实现 UITextFieldDelegate 的 textFieldShouldBeginEditing 方法以清除文本并将颜色更改回正常。您还必须实现 textFieldShouldClear 和 textFieldDidEndEditing 方法来替换 UITextField 中的伪占位符并将文本颜色更改回 70% 灰色。

      2:
      在 viewWillAppear 中,您可以将 UITextField 的文本设置为您的占位符,创建一个 UIFont 对象并将其设置为等于 UITextField 的字体属性,清除 UITextField 的文本,并将占位符设置为 NSAttributedString,并将字体对象作为属性。这是我的意思的一个例子:

      -(void)viewWillAppear:(BOOL) animated {
          [super viewWillAppear:animated];
          someTextField.adjustsFontSizeToFitWidth = YES;
          someTextField.text = @"placeholderText";
          UIFont *font = someTextField.font;
          someTextField.text = nil;
          NSDictionary *attributes = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
          NSAttributedString *placeholderString= [[NSAttributedString alloc] initWithString:@"placeholderText" attributes:attributes];
          someTextField.placeholder = placeholderString;
      }
      

      编辑:刚刚注意到 swift 标签。我用 Objective-C 编写了我的代码,但你应该能够轻松地将它翻译成 Swift。

      【讨论】:

      • 我认为您的解决方案更好。它根本不依赖 UITextField 实现。
      【解决方案4】:

      基于答案 9:在 Storyboard 中,转到文本字段元素的身份检查器选项卡,然后在“用户定义的运行时属性”部分下,添加以下内容:

      【讨论】:

        【解决方案5】:

        你可以创建UITextField的子类:

        class AutoSizeTextField: UITextField {
            override func layoutSubviews() {
                super.layoutSubviews()
        
                for subview in subviews {
                    if let label = subview as? UILabel {
                        label.minimumScaleFactor = 0.3
                        label.adjustsFontSizeToFitWidth = true
                    }
                }
            }
        }    
        

        或者您可以在视图控制器的viewDidAppear 中添加一些代码:

        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
        
            for subview in fieldTest.subviews {
                if let label = subview as? UILabel {
                    label.minimumScaleFactor = 0.3
                    label.adjustsFontSizeToFitWidth = true
                }
            }
        }
        

        【讨论】:

        • 第一个解决方案还不错,但最好添加递归查找所有 UILabel 子视图的功能,而不是应用相同的设置。
        • 我发现将这段代码放在 viewDidLayoutSubviews 中优于 viewDidAppear 因为它会在视图完全出现之前完成。
        【解决方案6】:

        斯威夫特

        随意改进扩展 - 很确定有一种更优雅的方式来迭代子视图。

        override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
        
            tfCountryCode.allSubviewsOfClass(UILabel.self).forEach {
                $0.adjustsFontSizeToFitWidth = true
                $0.minimumScaleFactor = 0.5
            }
        }
        
        extension UIView {
            func allSubviewsOfClass<K: UIView>(_ clazz: K.Type) -> [K] {
                var matches = [K]()
                if subviews.isEmpty { return matches }
                matches.append(contentsOf: subviews.filter { $0 is K } as! [K])
                let matchesInSubviews = subviews.flatMap { return $0.allSubviewsOfClass(clazz) }
                matches.append(contentsOf: matchesInSubviews.flatMap { $0 })
                return matches
            }
        }
        

        【讨论】:

          【解决方案7】:

          整个方法或缩小字体大小以适应可访问性的时代和时代是错误的。

          首先,您首先指定文本大小的业务为零,更不用说进一步缩小:您必须依赖可访问性 API。

          因此,如果占位符可能不适合,则必须放置 作为 UITextField 之前的 UILabel。占位符应该是 SHORT 并且适合没有剪辑。

          要确定它是否被剪裁,我想你可以使用 - (CGRect)placeholderRectForBounds:(CGRect)bounds;但是你在 使用 API 的浑水,Apple 说你应该只覆盖它(但不要调用你自己,即使它可能是有意义和安全的 在 didlayoutsubviews 方法的范围内)

          如果占位符文本是动态的(服务器提供),则将其转储到 UILabel。

          【讨论】:

            【解决方案8】:
             override func viewDidAppear(_ animated: Bool) {
                    super.viewDidAppear(animated)
                   for subView in fieldTest.subviews{
                    if subView .isKind(of: UILabel.self){
                        let label = subView as! UILabel
                        label.adjustsFontSizeToFitWidth = true
                        label.minimumScaleFactor = 0.2
                    }
                }     
            }
            

            【讨论】:

            • 如果 Apple 更改视图层次结构,这将崩溃。
            • @Iulian Onofrei 非常感谢。我已经更新了代码。
            【解决方案9】:

            在斯威夫特中

            yourTextField.subviews
                    .filter { $0 is UILabel }
                    .flatMap { $0 as? UILabel }
                    .forEach {
                        $0.adjustsFontSizeToFitWidth = true
                        $0.minimumScaleFactor = 0.5
                    }
            

            它有效:)

            【讨论】:

            • 你真的需要both filter flatMap吗?在这种情况下,flatMap 不应该就可以了吗?也就是将UIView的数组映射成UILabel的数组(丢弃向下转换失败的元素)?
            【解决方案10】:

            这是一个解决方案,它取决于未记录的事实,即 UITextField 有一个子 UILabel(实际上是 UITextFieldLabel)来呈现占位符。此解决方案相对于其他一些解决方案的优势在于,如果 Apple 的实施发生变化,它会优雅地降级。它也不会对无证 ivars 的存在做出假设。

            基本上我们通过一个类别来扩展 UILabel。如果我们看到自己的父母是UITextField,那么我们打开adjustFontSizeToFitWidth

            @interface UILabel (TS)
            @end
            
            @implementation UILabel (TS)
            
            - (void) didMoveToSuperview
            {
                [super didMoveToSuperview];
            
                if ( [self.superview isKindOfClass: [UITextField class]] ) {
            
                    self.adjustsFontSizeToFitWidth = YES;
                }
            }
            
            @end
            

            【讨论】:

            • 这将改变整个项目的行为。同时它并不比 wj2061 的解决方案好,因为你们两个都不是递归地迭代子视图。
            • @TimurBernikowich 你说得非常正确——它会改变应用程序中的全局行为。如果您不希望在其他地方出现这种行为,它可能不是一个完整的解决方案。让它更健壮是直截了当的;我只提出一个基本技术。 IMO,在可能发生的任何地方调整过长占位符文本的字体大小并不是一个坏行为。
            【解决方案11】:

            给你:

            _myTextField.placeholder = @"SomeTextSomeTextSome";
            UILabel *label = [_myTextField valueForKey:@"_placeholderLabel"];
            label.adjustsFontSizeToFitWidth = YES;
            

            干杯!!

            【讨论】:

            • 最好的解决方案!谢谢你,我的朋友!
            • 对于那些使用 swift 和 iOS 13 或其他东西替换 "_placeholderLabel" -> "placeholderLabel"
            【解决方案12】:

            您可以使用这两种解决方案:

            1.如果 Textfield 大小小于占位符文本,则您有固定字体大小:

                let placeholderString = testTF.placeholder
            
                print(placeholderString!)
            
                let font = UIFont(name: (testTF.font?.fontName)!, size: 16)!
            
                let fontAttributes = [NSFontAttributeName: font]
            
                let size = (placeholderString! as NSString).sizeWithAttributes(fontAttributes)
            
                print(size)
                print(testTF.frame.size.width)
                if(size.width > testTF.frame.size.width)
                {
                    let font = UIFont(name: (testTF.font?.fontName)!, size: 4)!
                    let attributes = [
                        NSForegroundColorAttributeName: UIColor.lightGrayColor(),
                        NSFontAttributeName : font]
            
                    testTF.attributedPlaceholder = NSAttributedString(string: placeholderString!,
                                                                      attributes:attributes)
            
            
                }
                else
                {
                let attributes = [
                    NSForegroundColorAttributeName: UIColor.lightGrayColor(),
                    NSFontAttributeName : font]
            
                testTF.attributedPlaceholder = NSAttributedString(string: placeholderString!,
                                                                     attributes:attributes)
                }
            

            2) 如果您想要动态字体大小,则只需检查上述条件的文本字段宽度和占位符文本 size.width。如果占位符文本大小大于文本字段大小,则在文本字段内创建一个标签并在其上设置最小字体。

            if(size.width > testTF.frame.size.width) {

                    placeholder = UILabel(frame: CGRect( x: 0, y: 0, width: testTF.bounds.width, height: testTF.bounds.height))
                    placeholder.text = placeholderString
                    placeholder.numberOfLines = 1;
                    //placeholder.minimumScaleFactor = 8;
                    placeholder.adjustsFontSizeToFitWidth = true
                    placeholder.textColor = UIColor.grayColor()
                    placeholder.hidden = !testTF.text!.isEmpty
                    placeholder.textAlignment = .Center
                    testTF.addSubview(placeholder)
            

            }

            【讨论】:

              【解决方案13】:

              尝试使用属性占位符而不是普通占位符

              试试这个

              let attributedplaceholder = NSAttributedString(string: "placeholdertext", attributes: [NSFontAttributeName: UIFont(name: "FontName", size: 10)!])
              self.fieldTest.attributedPlaceholder = attributedplaceholder
              

              您可以为占位符添加其他属性,例如 textcolor 和其他

              【讨论】:

              • 这对原始问题没有帮助。如果占位符文本太长,占位符仍然不会自动收缩以适应宽度。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-05-10
              • 2014-02-17
              • 2012-01-21
              • 1970-01-01
              • 2019-06-22
              • 2010-11-23
              • 2016-10-07
              相关资源
              最近更新 更多