Last active
August 29, 2015 14:23
-
-
Save jpmhouston/35686fc811b1c62effe5 to your computer and use it in GitHub Desktop.
Shrink UITextField placeholder to fit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// call from a view controller's -viewDidLayoutSubviews or -viewWillAppear: | |
// pass it a text field, etc, assign result to that text field's attributedPlaceholder property | |
// note that the maxKerning parameter must be a negative value (a "maximally negative" kerning value) | |
// pro tip: i've sometimes found that a text field still has incorrect bounds in -viewDidLayoutSubviews | |
// and needs to forcibly have its layout done: | |
//- (void)viewDidLayoutSubviews { | |
// [self.field layoutIfNeeded]; | |
// self.field.attributedPlaceholder = [self resizedPlaceholderForField:self.field withPadding:4.0 maxKerningReduction:0.3]; | |
//} | |
- (NSAttributedString *)resizedPlaceholderForField:(UITextField *)field withPadding:(CGFloat)extraPadding maxKerningReduction:(double)maxKerning | |
{ | |
NSAttributedString *placeholder = field.attributedPlaceholder; | |
UIFont *font = [placeholder attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL]; | |
if (!font) { | |
return placeholder; | |
} | |
CGFloat fontSize = font.pointSize; | |
NSMutableAttributedString *mutablePlaceholder = placeholder.mutableCopy; | |
CGSize boundsSize = [field placeholderRectForBounds:field.bounds].size; | |
CGSize unlimitedSize = (CGSize){ FLT_MAX, boundsSize.height }; | |
CGFloat maxWidth = boundsSize.width - extraPadding - extraPadding; | |
CGFloat fontDecrement = 0.5; | |
CGFloat kernDecrement = 0.05; | |
// if doesn't fit, first tighten the letter spacing by increments of .05 | |
BOOL fits = NO; | |
double kern = 0; // goes down from 0, since loop condition being 'kern > maxKerning', will skip this loop is maxKerning >= 0 | |
while (!fits && kern > maxKerning) { | |
CGRect measuredRect = [mutablePlaceholder boundingRectWithSize:unlimitedSize options:0 context:nil]; | |
if (!(fits = measuredRect.size.width <= maxWidth)) { | |
kern -= kernDecrement; | |
[mutablePlaceholder addAttribute:NSKernAttributeName value:@(kern) range:(NSRange){0, mutablePlaceholder.string.length}]; | |
} | |
} | |
// as long as it still doesn't fit, reduce the text size by .5 and try again, down to its minimum | |
while (!fits && fontSize >= field.minimumFontSize) { | |
CGRect measuredRect = [mutablePlaceholder boundingRectWithSize:unlimitedSize options:0 context:nil]; | |
if (!(fits = measuredRect.size.width <= maxWidth)) { | |
fontSize -= fontDecrement; | |
font = [font fontWithSize:fontSize]; | |
[mutablePlaceholder addAttribute:NSFontAttributeName value:font range:(NSRange){0, mutablePlaceholder.string.length}]; | |
} | |
} | |
return mutablePlaceholder; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment