12

I tried to subclass UITextField to draw custom placehoder. In iOS 6 this works fine but in iOS 7 I got a different CGRect height.

The UITextField frame is (0, 0, 500, 45). I added a left padding of 20 by overriding - (CGRect)editingRectForBounds:(CGRect)bounds;

- (CGRect)placeholderRectForBounds:(CGRect)bounds;

- (CGRect)textRectForBounds:(CGRect)bounds;

Calling the method below to do so:

- (CGRect)makeRectFromBounds:(CGRect)bounds
              withTopPadding:(CGFloat)topPadding
              andLeftPadding:(CGFloat)leftPadding
{
    return UIEdgeInsetsInsetRect(bounds, UIEdgeInsetsMake(topPadding, leftPadding, 0, 0));

}

Because I want a different placeHolder text color, I override

- (void)drawPlaceholderInRect:(CGRect)rect

- (void)drawPlaceholderInRect:(CGRect)rect {

    [[UIColor colorWithRed:121.0/255.0
                     green:113.0/255.0
                      blue:107.0/255.0
                     alpha:1.0] setFill];

    [self printRect:rect from:__FUNCTION__];

    [[self placeholder] drawInRect:rect withFont:self.font];
}

The rectangle I'm printing is the following:

iOS 7: -Rect (X: 0.0, Y:0.0, W:480.0, H:44.0)

iOS 6: -Rect (X: 0.0, Y:0.0, W:480.0, H:26.0)

Any idea if this is a bug or am I doing something wrong?

Jitender Dev
  • 6,907
  • 2
  • 24
  • 35
Cyupa
  • 1,126
  • 13
  • 37
  • I had the same problem and the best solution for me is: [Set custom color and draw placeholder vertically centered on iOS 5/6/7](http://stackoverflow.com/a/19220775/2243451) – Marius Kažemėkaitis Oct 07 '13 at 09:16

7 Answers7

6

Use the following instead:

[textfield setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
Ricky
  • 86
  • 1
4

In iOS 7 the default value for contentVerticalAlignment changed from "top" to "center" (with no documentation that I could see). In "center" mode iOS adjusts the result of the rectForBounds methods before drawing into them. You should probably set contentVerticalAlignment = UIControlContentVerticalAlignmentTop when overriding any of textRectForBounds methods so iOS will use the rect exactly as specified.

Ben Darnell
  • 21,844
  • 3
  • 29
  • 50
  • 2
    Tried it. In my case, I need it in the center, so I set it to UIControlContentVerticalAlignmentCenter and it's still aligned to the top. – Cyupa Sep 25 '13 at 07:45
  • Could you set contentVerticalAlignment to "top" and then center it yourself in textRectForBounds? If it's top-aligned I think iOS will use whatever rect you give it; it only has to change things if it's center-aligned. – Ben Darnell Sep 25 '13 at 21:47
  • @Cyupa, I am facing the same issue. Did you get any work around? – Heena Sep 30 '13 at 11:51
  • @Roshni Hi, no. I wasn't able to find a logical, documented explanation to this behavior. The solution was a dirty if check on the systemVersion property on the UIDevice singleton. I am not pleased with it, but it will do until I find the real reason. – Cyupa Sep 30 '13 at 13:20
2

Since iOS7 is new nowadays, so many people faces framing issue with iOS7.

To all of them, I just want say that it is so easy and there isn't any issue with iOS7. It's just because you don't know how to take benefits from the latest OS feature provided by Apple.

@Cyupa : You just need to apply autosizing and mask your textfield.

it could be one or more from following.

  • UIViewAutoresizingFlexibleBottomMargin
  • UIViewAutoresizingFlexibleTopMargin
  • UIViewAutoresizingFlexibleLeftMargin
  • UIViewAutoresizingFlexibleRightMargin
  • UIViewAutoresizingFlexibleHeight
  • UIViewAutoresizingFlexibleWidth

if you apply proper autosizingmask to your textfield, you will get your desired frame for your view (Here textfield)

Niru Mukund Shah
  • 4,637
  • 2
  • 20
  • 34
  • Thanks for the suggestion but it has no effect. I do appreciate your idea and haven't taught of it in the first place. Sadly, it doesn't help. – Cyupa Oct 01 '13 at 07:31
1

I also met this problem, not found why yet, but if you want to have the same behavior on both iOS6 and iOS7, you can try this:

- (CGRect)textRectForBounds:(CGRect)bounds {
    CGRect rect = [super textRectForBounds:bounds];
    rect = CGRectMake(20, rect.origin.y-4, rect.size.width-20, rect.size.height);
    return rect;
}

and you may need to set:

theLabel.contentVerticalAlignment =UIControlContentVerticalAlignmentCenter;
0

check the system version and return the UIEdgeInsetsInsetRect(bounds, UIEdgeInsetsMake(topPadding, leftPadding, 0, 0));

you can check device version as

if(([[[UIDevice currentDevice] systemVersion] floatValue]>=7.0))
{

}
Muruganandham K
  • 5,271
  • 5
  • 34
  • 62
  • Yes, I know about this but I wouldn't call it a solution because the OS returns different values. I'm looking for the logical explanation of why that CGRect differs in iOS 7. Thanks anyway. – Cyupa Sep 20 '13 at 12:30
  • Likewise, I would like to know the real underlying issue as well and avoid fragmented fixes throughout the code like this. – phoganuci Sep 20 '13 at 20:14
  • Rick's suggestion was correct but I rushed in by focusing on the problem rather than what I expected from the UITextField. It's still weird, but it solves my problem, changing the placeholder text color. – Cyupa Oct 01 '13 at 11:43
0

i solved issue by using this property

textField.contentVerticalAlignment =UIControlContentVerticalAlignmentCenter;

It's working for both iOS6 and iOS7.

Nirav Jain
  • 5,088
  • 5
  • 40
  • 61
-3

Ricky's solution worked for me with the addition this value has to be set each time AFTER placeholder text changed. I overwrote setPlaceholder to do that.

It replaces the need to overwrite drawPlaceholderInRect, if you want another placeholder color, therefore vertical alignment will be correct automatically. Of course this does not answer the question, why IOS 7.0 behaves like that, but it might solve your actual problem.

- (void) setPlaceholder: (NSString*)placeholderText {

    [super setPlaceholder:placeholderText];

    [self setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
}

It should be mentioned, that some people discourage this bypassing of public interfaces, so do it on your own risk! See also: Change UITextField's placeholder text color programmatically

Community
  • 1
  • 1
Tharagon
  • 117
  • 4
  • No, it does not work, I have tried it, even tough I did not believed it would actually work. What does the placeholder color has to do with the placeholder frame? – Cyupa Sep 30 '13 at 15:34
  • 1
    As you wrote yourself: "Because I want a different placeHolder text color, I override drawPlaceholderInRect". This is the connection. If you do NOT overwrite it, vertical alignment will be correct, regardless of contentVerticalAlignment - at least as long as you don't overwrite other functions, that might mess up the rect (e.g. for your left padding). Please vote this down, too, if you think, I lie to you, by saying it worked for me, and / or I dont know what I'm talking about. – Tharagon Oct 01 '13 at 09:57
  • Oh, I see now. Sorry about that. I got confused, I focused on the problem (the rect size) rather than what I was looking after in the first place: changing the placeholder text color. So I'll give you the bounty for the explanation and I'll have to apologize. Thanks for the help. But I'll have to give Ricky the correct answer because he was first and I rushed in like a fool with him too. – Cyupa Oct 01 '13 at 11:38