2

I have a custom UITextField so that I get get a custom placeholder text color as may answers suggest. However, I also want to change the color of the placeholder text at runtime, so I created a property.

// Overide the placholder text color
- (void) drawPlaceholderInRect:(CGRect)rect
{
    [self.placeholderTextColor setFill];
    [self.placeholder drawInRect:rect
                        withFont:self.font
                   lineBreakMode:UILineBreakModeTailTruncation
                       alignment:self.textAlignment];
}

- (void) setPlaceholderTextColor:(UIColor *)placeholderTextColor
{
    // To verify this is being called and that the placeholder property is set
    NSLog(@"placeholder text: %@", self.placeholder); 

    _placeholderTextColor = placeholderTextColor;
    [self setNeedsDisplay]; // This does not trigger drawPlaceholderInRect
}

The problem is the docs say I should not call drawPlaceholderInRect directly, and [self setNeedsDisplay]; dons't work. Any ideas?

Robert
  • 37,670
  • 37
  • 171
  • 213

3 Answers3

6

The drawPlaceholderInRect: method is only called if the textfield actually contains a placeholder string. (it doesn't by default)

Try to set a placeholder string for your textfield in Interface Builder.
Also make sure you set your subclass in the Custom Class field.

Update:
I tried the reproduce the issue described in the question and also ran into that problem. According to this Stack Overflow question this seems to be a common problem: https://stackoverflow.com/a/2581866/100848.

As a workaround (at least when targeting iOS >= 6.0), you could use UITextField's attributedPlaceHolder:

NSMutableAttributedString* attributedString = [[NSMutableAttributedString alloc] initWithString:@"asdf"];
NSDictionary* attributes = @{NSForegroundColorAttributeName:[UIColor redColor]};
[attributedString setAttributes:attributes range:NSMakeRange(0, [attributedString length])];
[self.textField setAttributedPlaceholder:attributedString];
Community
  • 1
  • 1
Thomas Zoechling
  • 34,177
  • 3
  • 81
  • 112
4

You can also achieve this by subclassing the UITextField and overriding drawPlaceholderInRect

- (void) drawPlaceholderInRect:(CGRect)rect {
    if (self.useSmallPlaceholder) {
        NSDictionary *attributes = @{
                                 NSForegroundColorAttributeName : kInputPlaceholderTextColor,
                                 NSFontAttributeName : [UIFont fontWithName:kInputPlaceholderFontName size:kInputPlaceholderFontSize]
                                 };

        //center vertically
        CGSize textSize = [self.placeholder sizeWithAttributes:attributes];
        CGFloat hdif = rect.size.height - textSize.height;
        hdif = MAX(0, hdif);
        rect.origin.y += ceil(hdif/2.0);

        [[self placeholder] drawInRect:rect withAttributes:attributes];
    }
    else {
        [super drawPlaceholderInRect:rect];
    }
}

http://www.veltema.jp/2014/09/15/Changing-UITextField-placeholder-font-and-color/

Steven Veltema
  • 2,140
  • 15
  • 18
0

Add class level variable:

float forcePlaceHolderDraw;

Add this code into your subclass:

- (CGRect)placeholderRectForBounds:(CGRect)bounds {
if (forcePlaceHolderDraw == 0) {
        forcePlaceHolderDraw = 0.000001;
    } else {
        forcePlaceHolderDraw = 0;
    }
    return CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.width + forcePlaceHolderDraw, bounds.size.height);
}

I think given that old and new frame are same, the force draw is not working