UITableViewHeaderFooterView in iOS 8
Asked Answered
U

4

8

I have a UITableViewHeaderFooterView in which I change the textLabel font and the background color

UITableViewHeaderFooterView* header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"header"];
if(!header)
{
    header = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:@"header"];
    [header.textLabel setFont:[UIFont boldSystemFontOfSize:15]];
    [header.contentView setBackgroundColor:[UIColor colorWithRed:213/255.0 green:213/255.0 blue:213/255.0 alpha:1]];
}

Here is how iOS 7 shows it: enter image description here

Here is how iOS 8 shows it: enter image description here The setFont: doesn't seems to take effect here, or the 15pt font is bigger on iOS 8 that on iOS 7

Here is how iOS 8 shows it when I remove the setFont: call enter image description here

As you can see, setFont has no effect on the font, but it has on the textColor.

Am I missing something or those are "beta bugs" (I'm using simulators from XCode6 GM seed, and I have the same issue on a iPhone 5 with iOS 8 beta 5) ?

Edit: iOS 8 release and XCode 6.0.1 doesn't seems to fix the problem

Umpteen answered 17/9, 2014 at 10:22 Comment(2)
I'm having headaches with this and font management enttirely in iOS 8 for days!!!Cheshvan
I could not change font and background color of UITableViewHeaderFooterView, both get reset by the time the view is presented. Checked on iOS 9.3. So I ended up with making view adjustments in tableView:willDisplayHeaderView:forSection: as suggested in https://mcmap.net/q/174899/-troubles-with-changing-the-font-size-in-uitableviewheaderfooterviewBiting
U
-1

Based on tubtub's answer, I made a UITableViewHeaderFooterView subclass:

@interface CompatibilityTableViewHeaderFooterView : UITableViewHeaderFooterView
@property (nonatomic,readonly) UILabel* compabilityTextLabel;
@end

@implementation CompatibilityTableViewHeaderFooterView
{
    UILabel* iOS8TextLabel;
    NSLayoutConstraint* iOS8TextLabelLeftMarginConstraint;
}

-(instancetype) initWithReuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithReuseIdentifier:reuseIdentifier])
    {
        self.contentView.backgroundColor = GRIS_213;
        self.compabilityTextLabel.font = [UIFont boldSystemFontOfSize:15];
    }
    return self;
}

-(UILabel*) compabilityTextLabel
{
    if ([UIDevice currentDevice].systemVersion.floatValue < 8.0)
    {
        return self.textLabel;
    }
    else
    {
        if (!iOS8TextLabel)
        {
            iOS8TextLabel = [[UILabel alloc] init];
            iOS8TextLabel.translatesAutoresizingMaskIntoConstraints = NO;

            [self addSubview:iOS8TextLabel];

            iOS8TextLabelLeftMarginConstraint = [NSLayoutConstraint constraintWithItem:iOS8TextLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:0];

            [self addConstraint:iOS8TextLabelLeftMarginConstraint];
            [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[iOS8TextLabel]-(>=0)-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(iOS8TextLabel)]];
            [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[iOS8TextLabel]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(iOS8TextLabel)]];
        }
        return iOS8TextLabel;
    }
}

-(UITableView*) searchForTableView
{
    UIView* currentView = self;
    while (currentView)
    {
        currentView = currentView.superview;
        if ([currentView isKindOfClass:[UITableView class]])
        {
            return (UITableView*)currentView;
        }
    }
    return nil;
}

-(void) layoutSubviews
{
    [super layoutSubviews];

    UITableView* tableView = [self searchForTableView];
    if (tableView)
    {
        iOS8TextLabelLeftMarginConstraint.constant = tableView.separatorInset.left;
    }
}

So basically I now only use the compabilityTextLabelproperty instead of textLabel. Note that the left space constraint is automatically updated to match the tableView separator inset. Feel free to comment/improve my code ;)

Umpteen answered 30/9, 2014 at 14:30 Comment(0)
P
3

[SWIFT version] Just had the same problem in UITableView UITableViewStylePlain , i.e. Header font setting in

override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) {...} 

has no effect. Here is code from my subclass of UITableViewController what worked for me [tested with XCode 6.4, iOS 8.4], see http://www.elicere.com/mobile/swift-blog-2-uitableview-section-header-color/

override func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    let header = view as? UITableViewHeaderFooterView //recast your view as a UITableViewHeaderFooterView
    if (header == nil) {
      return;
    }
    if (myHeaderFont != nil) {
      header!.textLabel.font = myHeaderFont;
    } 
  }

The header height needs to be "manually" adjusted:

override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if (myHeaderFont == nil) {
  return  20; //DEFAULT_HEADER_HEIGHT_IN_POINTS;
}
return myHeaderFont.pointSize * 2; //HEIGHT_REL_TO_FONT;

}

The rest was standard, but showing here for completeness:

override func viewDidLoad() {
//...
//https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewHeaderFooterView_class/index.html#//apple_ref/doc/uid/TP40012241
    self.tableView.registerClass(UITableViewHeaderFooterView.self, forHeaderFooterViewReuseIdentifier: "HEADER_REUSE_ID")
 //...
}
      override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        var header = tableView.dequeueReusableHeaderFooterViewWithIdentifier("HEADER_REUSE_ID") as? UITableViewHeaderFooterView;
        if (header == nil) {
          header = UITableViewHeaderFooterView(reuseIdentifier: "HEADER_REUSE_ID");
        }
        header!.textLabel.text = myTitle;
        return header!;
      }
Portent answered 17/7, 2015 at 2:19 Comment(0)
R
0

I was having the same problem and ended up with subclassing UITableViewHeaderFooterView.

Here's a small reference implementation: Just set header.headerLabel.text = @"myString";.

@interface BHRSectionHeaderView : UITableViewHeaderFooterView

@property (nonatomic, strong) UILabel *headerLabel;

@end



@implementation BHRSectionHeaderView

- (UILabel *)headerLabel
{
    if (!_headerLabel)
    {
        _headerLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        _headerLabel.font = [UIFont boldSystemFontOfSize:13.f];
        _headerLabel.textColor = [UIColor redColor];

        _headerLabel.translatesAutoresizingMaskIntoConstraints = NO;
        [self addSubview:_headerLabel];

        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(16)-[header]-(>=0)-|"
                                                                 options:0
                                                                 metrics:nil
                                                                   views:@{ @"header": _headerLabel }]];

        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=0)-[header]-(>=0)-|"
                                                                 options:0
                                                                 metrics:nil
                                                                   views:@{ @"header": _headerLabel }]];

        [self addConstraint:[NSLayoutConstraint constraintWithItem:_headerLabel
                                                     attribute:NSLayoutAttributeCenterY
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:self
                                                     attribute:NSLayoutAttributeCenterY
                                                    multiplier:1.0f
                                                      constant:0.0f]];
    }

    return _headerLabel;
}

@end
Retrochoir answered 19/9, 2014 at 15:38 Comment(2)
Why did you choose to create a UITableViewHeaderFooterView subclass instead of just having a UILabel?Umpteen
I wanted to take benefit of UITableView's reuse and I'm using the backgroundView property on UITableViewHeaderFooterView. Returning a UILabel (or any other UIView subclass) should work as well.Retrochoir
U
0

You can modify the textLabel font by overriding the -layoutSubviews method:

- (void)layoutSubviews
{
    self.textLabel.font = [UIFont boldSystemFontOfSize:15.0f];
    self.textLabel.textAlignment = NSTextAlignmentCenter;
    self.textLabel.textColor = [UIColor grayColor];

    [super layoutSubviews];
}
Uptown answered 31/3, 2015 at 6:25 Comment(3)
layoutSubviews should only contain layout logic!Fransis
True, this is a hack. It's a way to get access to a simple UITableViewCell's objects without having to completely rewrite the table view cell. If you were to do that, you wouldn't put these commands in -layoutSubviews. Calling these in the correctly place on a UITableViewCell doesn't work. But this is simple, effective, and IMHO, safe.Uptown
I know it looks simple, but there are other ways around these things than hacking the layoutSubviews and hoping for the best; what would happen if one of the setters requested another layout? You would get stuck in an infinite loop... You don't have to completely rewrite the header/footer view, just subclassing works fine - I found that exposing a public method on the subclass (i.e. configureWithText:(NSString *)text) and calling it in will display header from UITableViewDelegate works out fine.Fransis
U
-1

Based on tubtub's answer, I made a UITableViewHeaderFooterView subclass:

@interface CompatibilityTableViewHeaderFooterView : UITableViewHeaderFooterView
@property (nonatomic,readonly) UILabel* compabilityTextLabel;
@end

@implementation CompatibilityTableViewHeaderFooterView
{
    UILabel* iOS8TextLabel;
    NSLayoutConstraint* iOS8TextLabelLeftMarginConstraint;
}

-(instancetype) initWithReuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithReuseIdentifier:reuseIdentifier])
    {
        self.contentView.backgroundColor = GRIS_213;
        self.compabilityTextLabel.font = [UIFont boldSystemFontOfSize:15];
    }
    return self;
}

-(UILabel*) compabilityTextLabel
{
    if ([UIDevice currentDevice].systemVersion.floatValue < 8.0)
    {
        return self.textLabel;
    }
    else
    {
        if (!iOS8TextLabel)
        {
            iOS8TextLabel = [[UILabel alloc] init];
            iOS8TextLabel.translatesAutoresizingMaskIntoConstraints = NO;

            [self addSubview:iOS8TextLabel];

            iOS8TextLabelLeftMarginConstraint = [NSLayoutConstraint constraintWithItem:iOS8TextLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:0];

            [self addConstraint:iOS8TextLabelLeftMarginConstraint];
            [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[iOS8TextLabel]-(>=0)-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(iOS8TextLabel)]];
            [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[iOS8TextLabel]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(iOS8TextLabel)]];
        }
        return iOS8TextLabel;
    }
}

-(UITableView*) searchForTableView
{
    UIView* currentView = self;
    while (currentView)
    {
        currentView = currentView.superview;
        if ([currentView isKindOfClass:[UITableView class]])
        {
            return (UITableView*)currentView;
        }
    }
    return nil;
}

-(void) layoutSubviews
{
    [super layoutSubviews];

    UITableView* tableView = [self searchForTableView];
    if (tableView)
    {
        iOS8TextLabelLeftMarginConstraint.constant = tableView.separatorInset.left;
    }
}

So basically I now only use the compabilityTextLabelproperty instead of textLabel. Note that the left space constraint is automatically updated to match the tableView separator inset. Feel free to comment/improve my code ;)

Umpteen answered 30/9, 2014 at 14:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.