ChatGPT解决这个技术问题 Extra ChatGPT

UITableViewHeaderFooterView: Unable to change background color

I'm trying to change the background color of UITableViewHeaderFooterView. Although the view is appearing, the background color remains the default color. I'm getting a log from xcode saying:

Setting the background color on UITableViewHeaderFooterView has been deprecated. Please use contentView.backgroundColor instead.

However, none of the following options work:

myTableViewHeaderFooterView.contentView.backgroundColor = [UIColor blackColor];
myTableViewHeaderFooterView.backgroundView.backgroundColor = [UIColor blackColor];
myTableViewHeaderFooterView.backgroundColor = [UIColor blackColor];

I've also tried changing the background color of the view in the xib file.

Any suggestions? Thanks.

in iOS 13, use contentView.backgroundColor worked for me. I think Apple updated this

S
SwiftArchitect

iOS 8, 9, 10, 11...

The only way to set any color (with any alpha) is to use backgroundView:

Swift

self.backgroundView = UIView(frame: self.bounds)
self.backgroundView.backgroundColor = UIColor(white: 0.5, alpha: 0.5)

Obj-C

self.backgroundView = ({
    UIView * view = [[UIView alloc] initWithFrame:self.bounds];
    view.backgroundColor = [UIColor colorWithWhite: 0.5 alpha:0.5];
    view;
    });

Responses to Comments

None of these other options reliably work (despite the comments below) // self.contentView.backgroundColor = [UIColor clearColor]; // self.backgroundColor = [UIColor clearColor]; // self.tintColor = [UIColor clearColor];

the backgroundView is resized automatically. (No need to add constraints)

Control alpha with UIColor(white: 0.5, alpha: 0.5) or backgroundView.alpha = 0.5. (of course, any color will do)

When using XIB, make root view a UITableViewHeaderFooterView and associate the backgroundView programmatically: Register with: tableView.register(UINib(nibName: "View", bundle: nil), forHeaderFooterViewReuseIdentifier: "header") Load with: override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { if let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "header") { let backgroundView = UIView(frame: header.bounds) backgroundView.backgroundColor = UIColor(white: 0.5, alpha: 0.5) header.backgroundView = backgroundView return header } return nil }

https://i.stack.imgur.com/2dvo5.gif

↻ replay animation

► Find this solution on GitHub and additional details on Swift Recipes.


contentView doesnt exist that's why. tintcolor is to tint the view not its background. and backgroundcolor is deprecated. Thus your way is the way to make it to work. Btw nice code syntax
@JoãoNunes, with C# / Xamarin the syntax is even neater: view.BackgroundView = new UIView(view.Bounds) { BackgroundColor = UIColor.Clear };
In Xcode 6.1.1, you get a run-time console warning: Setting the background color on UITableViewHeaderFooterView has been deprecated. Please use contentView.backgroundColor instead.
With Xcode6.2 beta5, I still got same warning. My creation method of UITableViewHeaderFooterView is based on loading xib which is similar to Apple sample code, TVAnimationsGestures. However, TVAnimationGestures with Xcode6.2b5 does not generate any warning message. Apple code does not have 'background' string at all. Of course, uitableVuewHeaderFooterview.contentView is nil in TVAnimationsGestures. I don't understand why this happen.
For people who still get the warning: make sure the UITableViewHeaderFooterView doesn't have a backgroundColor set in IB.
a
aheze

You should either use myTableViewHeaderFooterView.tintColor, or assign a custom background view to myTableViewHeaderFooterView.backgroundView.


myTableViewHeaderFooterView.tintColor works perfectly. Thanks for the answer!
Don't know why, but for me tintColor not working on iOS7. I could change color only by assign custom view: myTableViewHeaderFooterView.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"myImage.png"]];
TintColor is not background color!!
Overriding .tintColor works if your view background is set to Default color instead of System Background Default color. But should not be using it as it is supposed to be tint color, not background color.
s
sash

In iOS 7 contentView.backgroundColor worked for me, tintColor did not.

   headerView.contentView.backgroundColor = [UIColor blackColor];

Though clearColor did not work for me, the solution I found is to set backgroundView property to transparent image. Maybe it will help someone:

UIGraphicsBeginImageContextWithOptions(CGSizeMake(1, 1), NO, 0.0);
UIImage *blank = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

headerView.backgroundView = [[UIImageView alloc] initWithImage:blank];

I think this is a better approach than @SwiftArchitect 's answer (Although it worked). The fact you don't have to add a new UIView makes it way better. Worked perfectly for me.
R
Rudolf J

Make sure you set the backgroundColor of the contentView for your UITableViewHeaderFooterView:

self.contentView.backgroundColor = [UIColor whiteColor];

Then it will work.


iOS >=10 only!. For iOS <10 use: backgroundView?.backgroundColor = UIColor.white
A
AmJa

https://i.stack.imgur.com/DqtIq.png

https://i.stack.imgur.com/IyLTN.png


E
Eneko Alonso

For solid background colors, setting the contentView.backgroundColor should be enough:

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    if let headerView = view as? UITableViewHeaderFooterView {
        headerView.contentView.backgroundColor = .red // Works!
    }
}

For colors with transparency, including .clear color, this no longer works:

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    if let headerView = view as? UITableViewHeaderFooterView {
        headerView.contentView.backgroundColor = .clear // Does not work 😞
    }
}

For a full transparent section header, set the backgroundView property to an empty view:

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    if let headerView = view as? UITableViewHeaderFooterView {
        headerView.backgroundView = UIView() // Works!
    }
}

However, beware of possible side effects. Unless the table view is set to "Grouped", section headers will snap at the top when scrolling down. If the section headers are transparent, the cell content will be seen through, which might not look great.

Here, section headers have transparent background:

https://i.stack.imgur.com/eT1Up.gif

To prevent this, it is better to set the background of the section header to a solid color (or gradient) matching the background of your table view or view controller.

Here, section headers have a fully opaque gradient background:

https://i.stack.imgur.com/DRISs.gif


Genius! Defining an empty UIView for backgroundView totally solved the issue for me! Thanks!
C
ChildhoodAndy

For a clear color, I use

self.contentView.backgroundColor = [UIColor clearColor];
self.backgroundView = [UIView new];
self.backgroundView.backgroundColor = [UIColor clearColor];

It seems fine to me.


Setting backgroundView = UIView() and then backgroundColor = .clear was the only working solution. Thank you.
H
Hosny

https://i.stack.imgur.com/mcuFA.png


J
Jan

On iOS9 headerView.backgroundView.backgroundColor worked for me:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    TableViewHeader *headerView = (TableViewHeader *)[super tableView:tableView viewForHeaderInSection:section];
    headerView.backgroundView.backgroundColor = [UIColor redColor];
}

On iOS8 I was using headerView.contentView.backgroundColor without problems, but now with iOS 9, I was getting a weird issue that made the background color not fill the whole space of the cell. So I tried just headerView.backgroundColor and I got the same error from the OP.

Setting the background color on UITableViewHeaderFooterView has been deprecated. Please use contentView.backgroundColor instead.

So now everything works great and without warnings by using headerView.backgroundView.backgroundColor


J
Jagat Dave

if you created a custom subclass of UITableViewHeaderFooterView with xib file then you should override setBackgroundColor. Keep it empty.

-(void)setBackgroundColor:(UIColor *)backgroundColor {

}

And this will solve your problem.


This is correct answer for me. Althought I don't set any background color in my HeaderFooterView but the warning message keeps come out in my console log. So annoying!
s
samwize

If you are customising a section header cell with Storyboard/Nib, then make sure the background color is default for the "Table Section Header" view.

And if you subclass UITableViewHeaderFooterView, and using nib, then what you have to do is to create a IBOutlet for the content view, and name it eg. containerView. This is not to be confused with contentView, which is parent of this container view.

With that setup, you change the background color of containerView instead.


t
tylyo

I tried with the appearanceWhenContainedIn chain, and it worked for me.

[[UIView appearanceWhenContainedIn:[UITableViewHeaderFooterView class], [UITableView class], nil] 
         setBackgroundColor: [UIColor.grayColor]];

a
andrew54068

maybe because the backgroundView doesn't exist

override func draw(_ rect: CGRect){
    // Drawing code
    let view = UIView()
    view.frame = rect
    self.backgroundView = view
    self.backgroundView?.backgroundColor = UIColor.yourColorHere
}

that work for me.


E
Eli Burke

iOS 12, Swift 5. If you are willing (or trying!) to use an appearance proxy, the following solution works:

Subclass UITableViewHeaderFooterView and expose your own appearance proxy setting.

final class MySectionHeaderView: UITableViewHeaderFooterView {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(reuseIdentifier: String?) {
        super.init(reuseIdentifier: reuseIdentifier)
    }

    @objc dynamic var forceBackgroundColor: UIColor? {
        get { return self.contentView.backgroundColor }
        set(color) {
            self.contentView.backgroundColor = color
            // if your color is not opaque, adjust backgroundView as well
            self.backgroundView?.backgroundColor = .clear
        }
    }
}

Set the appearance proxy at your desired granularity.

MySectionHeaderView.appearance().forceBackgroundColor = .red

or

MySectionHeaderView.appearance(whenContainedInInstancesOf: [MyOtherClass.self]).forceBackgroundColor = .red

e
eli7ah

Forget about difficulties.

Add to your project UITableViewHeaderFooterView+BGUpdate.swift with code below:

extension UITableViewHeaderFooterView {

    open override var backgroundColor: UIColor? {
        get {
            return self.backgroundColor
        }
        set {
            let bgView = UIView()
            bgView.backgroundColor = newValue
            backgroundView = bgView
        }
    }
}

Usage is simple as you expected before:

headerView.backgroundColor = .red

Usage examples:

1) In delegate's tableView:viewForHeaderInSection: :

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let headerView = tv.dequeueReusableHeaderFooterView(withIdentifier: "MyHeaderView")
    headerView.backgroundColor = .red // <- here
    return headerView
}

or

2) In your custom header view class:

class MyHeaderView: UITableViewHeaderFooterView {

    override func awakeFromNib() {
        super.awakeFromNib()
        backgroundColor = .red // <- here
    }
}

Ok... your way is better. :) Thanks
This solution causes a recursive loop on iOS 12.
S
Shohin

Put this code in initializing of your UITableViewHeaderFooterView subclass:

let bgView = UIView()
bgView.backgroundColor = UIColor.clear
backgroundView = bgView
backgroundColor = UIColor.clear
contentView.backgroundColor = UIColor.clear

While this may answer the question, it was flagged for review. Answers with no explanation are often considered low-quality. Please provide some commentary in the answer for why this is the correct answer.
I got it. Thank you for your feedback.
a
aas

Setting the BackgroundView with clear color works fine for visible headers. If the table is scrolled to show headers at bottom ,this solution fails.

P.S.My table consists only of headers without any cells.


A
Alvin George

Swift:

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView {
    var headerView: TableViewHeader = super.tableView(tableView, viewForHeaderInSection: section) as! TableViewHeader
    headerView.backgroundView.backgroundColor = UIColor.redColor()
}

佚名

Create UIView and set background color, then set it to self.backgroundView.

- (void)setupBackgroundColor:(UIColor *) color {
    UIView *bgView = [[UIView alloc] initWithFrame:self.bounds];
    bgView.backgroundColor = color;
    self.backgroundView = bgView;
}

A
Ahmed Khedr

I feel compelled to share my experience. I had this piece of code that worked fine with iOS 10 and iOS 11 headerView?.contentView.backgroundColor = .lightGray

Then I all of a sudden decided to to deploy the app for iOS 9 as there are some devices (iPad mini some older generation doesn't update to any OS beyond 9) - The only solution that worked for all iOS 9, 10 and 11 was to define a base view for the header that then contains all other header subviews, wire it up from storyboard and set the backgroundColor of that base view.

You will want to be mindful when wiring the outlet not to call it: backgroundView as there is already a property with that name in some superclass. I called mine containingView

Also when wiring the outlet control click on the view in Document Outline to make sure it's not wired up to file owner


N
Naloiko Eugene

Now since iOS 14 we've got UIBackgroundConfiguration for UITableViewHeaderFooterView.

To change the background color I'm doing the following:

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    if let headerView = view as? LeftMenuSectionHeader {
        if var backgroundConfig = headerView.backgroundConfiguration {
            backgroundConfig.backgroundColor = UIColor.clear
            headerView.backgroundConfiguration = backgroundConfig
        }
    }
}