1

I'm using a UILabel as a custom view for my UIPickerView, and I'm trying to pad the label in from the left by 10px or so. However, no matter what frame I set the UILabel to, it gets ignored.

I'm basically trying to make a datepicker, with an "unknown" option in the year component. I'm a bit of a newbie to iOS dev. Is it possible/ would it be more elegant to subclass UIDatePicker and add the "unknown" option?

Here's my code:

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
    UILabel* tView = (UILabel*)view;

    if (!tView)
    {
        tView = [[UILabel alloc] initWithFrame:** Any CGRect here **];

        tView.backgroundColor = [UIColor redColor];
        tView.font = [UIFont boldSystemFontOfSize:16.0];

        if (component == 0)
        {
            tView.textAlignment = NSTextAlignmentCenter;
        }
    }

    // Set the title
    NSString *rowTitle;

    if (component == 0)
    {
        rowTitle = [NSString stringWithFormat:@"%d", (row + 1)];
    }
    else if (component == 1)
    {
        NSArray *months = [[NSArray alloc] initWithObjects:@"January", @"February", @"March", @"April", @"May", @"June", @"July", @"August", @"September", @"October", @"November", @"December", nil];
        rowTitle = (NSString *) [months objectAtIndex:row];
    }
    else if (component == 2)
    {
        if (row == 0)
        {
            rowTitle = @"- Unknown -";
        }
        else
        {
            NSDateFormatter *currentYearFormat = [[NSDateFormatter alloc] init];
            currentYearFormat.dateFormat = @"YYYY";
            NSInteger currentYear = [[currentYearFormat stringFromDate:[NSDate date]] intValue];

            rowTitle = [NSString stringWithFormat:@"%d", (currentYear - row)];
        }
    }

    tView.text = rowTitle;

    return tView;
}

Thanks!

Leon
  • 715
  • 1
  • 8
  • 22

1 Answers1

6

Don't use UILabel directly. The simplest way for you is to ...

Define width/height via ...

  • pickerView:widthForComponent:
  • pickerView:rowHeightForComponent:

... than create custom class based on UIView and return this object. In your custom UIView, add UILabel subview and move UILabel in layoutSubviews of your class. Something like this ...

// MyPickerView.h
@interface MyPickerView : UIView
  @property (nonatomic,strong,readonly) UILabel *label;
@end

// MyPickerView.m
@interface MyPickerView()
  @property (nonatomic,strong) UILabel *label;
@end

@implementation MyPickerView
  - (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if ( self ) {
      _label = [[UILabel alloc] initWithFrame:CGRectZero];
    }
    return self;
  }

  - (void)layoutSubviews {
    CGRect frame = self.bounds;
    frame.origin.x += 10.0f;
    frame.size.width -= 20.0f;
    _label.frame = frame;
  }
@end

... and return your MyPickerView in pickerView:viewForRow:forComponent:reusingView:.

zrzka
  • 20,249
  • 5
  • 47
  • 73
  • For such a simple case, wouldn't it be easier to simply prepend a few spaces at the start of the label's text. No need for a custom view. – rmaddy Oct 11 '12 at 20:25
  • 2
    @maddy WTF? Oh boy, this kind of hacks ... What if font will be changed? What if ... Do it properly ... – zrzka Oct 11 '12 at 20:26
  • 1
    The OP didn't state why they want an indent. I was just offering an alternative. Who knows? Maybe it would be appropriate for the indent to adjust along with the font size. So using spaces isn't necessarily an improper approach. Without more info either approach may be OK. – rmaddy Oct 11 '12 at 20:30
  • Sorry, but indenting by spaces is crazy. Something like indenting by spaces in Word, ... where people don't know tabs. – zrzka Oct 11 '12 at 20:31
  • Great code, it fixed my issue, thanks! One comment though... A call to [self addSubview:_label] is missing from initWithFrame: – Joshua Sep 26 '15 at 13:51