UITextField placeholder text: adjust to fit

我们两清 提交于 2019-12-14 00:17:08

问题


I have UITextField with longer text in it set as placeholder. What I want is for this placeholder text to adjust its font size when the width of field is too small.

I already tried this solution described in other posts (programmatically and in IB)

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

What am I missing here?


回答1:


You can create a subclass of 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
            }
        }
    }
}    

Or you can just add some code in your view controller's 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
        }
    }
}



回答2:


Here you go :

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

Cheers!!




回答3:


Based on answer 9: in Storyboard go to the identity inspector tab of the text field element, and under the "User Defined Runtime Attributes" section, add the following:




回答4:


Here's a solution that depends on the undocumented fact that the UITextField has a child UILabel (actually UITextFieldLabel) to render the placeholder. The advantage of this solution over some others is that it degrades gracefully should Apple's implementation change. It also doesn't make assumptions about the existence of undocumented ivars.

Basically we extend UILabel via a category. If we see ourselves being parented to a UITextField then we turn on adjustFontSizeToFitWidth.

@interface UILabel (TS)
@end

@implementation UILabel (TS)

- (void) didMoveToSuperview
{
    [super didMoveToSuperview];

    if ( [self.superview isKindOfClass: [UITextField class]] ) {

        self.adjustsFontSizeToFitWidth = YES;
    }
}

@end



回答5:


After reviewing the class reference for UITextField's, it seems that adjustsFontSizeToFitWidth only affects the the text property of the UITextField and not the placeholder property. While I don't know off the top of my head a way to get the placeholder to respond to adjustsFontSizeToFitWidth, I can suggest two hacky ideas that may give you the appearance that you want. Just be aware that I'm not near a Mac right now so I haven't tested these ideas:

1:
Since a placeholder is just text with a 70% gray color, you could set the label's text property to be whatever you need it to be, and then implement the UITextFieldDelegate's textFieldShouldBeginEditing method to clear the text and change the color back to normal. You would also have to implement the textFieldShouldClear and textFieldDidEndEditing methods to replace the pseudo-placeholder back in the UITextField and change the text color back to 70% gray.

2:
In viewWillAppear you could set the UITextField's text to what your placeholder should be, create a UIFont object and set it equal to the UITextField's font property, clear the UITextField's text, and set the placeholder to be an NSAttributedString with the font object as a property. Here's an example of what I mean:

-(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;
}

Edit: Just noticed the swift tag. I wrote my code in Objective-C, but you should be able to easily translate it to Swift.




回答6:


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



回答7:


Swift

Feel free to improve the extension - pretty sure there is a more elegant way to iterate over the subviews.

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



回答8:


You can use these two solution:

1.If You have fixed font size if Textfield size is less than placeholder text:

    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) If you want dynamic font size than you just check the above condition for width of textfield and placeholder text size.width. if the placeholder text size is greater than textfield size than create one label inside the textfield and set minimum font on that.

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)

}




回答9:


In Swift

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

it works :)




回答10:


Try using attributed placeholder instead of normal place holder

Try this

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

You can add additional attributes to the placeholder like textcolor and other




回答11:


The whole approach or shrinking font size to fit is misguided in the day and age of accessibility.

Firstly you have zero business specifying text size in the first place, let alone shrinking that further: you have to rely on the accessibility API.

Thus if the placeholder is likely to not fit it has to be placed as a UILabel preceding the UITextField. The placeholders are supposed to be SHORT and fit without clippage.

To determine if it's clipped I guess you could use - (CGRect)placeholderRectForBounds:(CGRect)bounds; but then you are in murky waters of using an API which Apple says you should only override (but not call yourself even though it's probably meaningful and safe within the confines of didlayoutsubviews method[s])

If placeholder text is dynamic (server served) dump it into a UILabel.



来源:https://stackoverflow.com/questions/33805900/uitextfield-placeholder-text-adjust-to-fit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!