Aaron Brethorst
Aaron Brethorst

Reputation: 763

Different background colors for the top and bottom of a UITableView

If you look at your Inbox in iPhone OS 3.0's Mail app, you'll see that swiping down displays a grayish background color above the UISearchBar.

Now, if you scroll down to the bottom of the table, you'll see that the background color at that end is white.

I can think of a couple ways of solving this problem, but they're pretty hacky:

Does anyone know what the "best practice" solution is for this problem? thanks.

Upvotes: 36

Views: 21316

Answers (13)

rbaldwin
rbaldwin

Reputation: 4848

SwiftUI solution

 var body: some View {
        
        NavigationView {
            
            List(data, id: \.self) { data in
                Text("\(data)")
            }
            .onAppear {
                let headerView = UIView(frame: CGRect(x: 0, y: -400, width: UIScreen.main.bounds.width, height: 400.0))
                headerView.backgroundColor = .lightGray
                UITableView.appearance().addSubview(headerView)
            }
            .navigationBarTitle("Title", displayMode: .inline)
        }
    }

enter image description here


If you want a different background color below the List then add another UIView to change the backgroundView:

let backgroundView = UIView()
backgroundView.backgroundColor = .black
UITableView.appearance().backgroundView = backgroundView

enter image description here

Upvotes: 0

Alessandro Francucci
Alessandro Francucci

Reputation: 1660

Swift 5.0+

Solution with an extension:

extension UITableView {

    func addTopBounceAreaView(color: UIColor = .white) {
        var frame = UIScreen.main.bounds
        frame.origin.y = -frame.size.height

        let view = UIView(frame: frame)
        view.backgroundColor = color

        self.addSubview(view)
    }
}

Usage: tableView.addTopBounceAreaView()

Upvotes: 21

Olof
Olof

Reputation: 5338

There´s good answers at Light gray background in “bounce area”...

Where i found this codesnipet (slightly modified) that works great:

CGRect frame = self.tableView.bounds;
frame.origin.y = -frame.size.height;
UIView* grayView = [[UIView alloc] initWithFrame:frame];
grayView.backgroundColor = [UIColor grayColor];
[self.tableView addSubview:grayView];
[grayView release];

Swift:

var frame = self.tableView.bounds
frame.origin.y = -frame.size.height
let grayView = UIView(frame: frame)
grayView.backgroundColor = .gray
self.tableView.addSubview(grayView)

Upvotes: 43

Alexey Rodionov
Alexey Rodionov

Reputation: 11

This is my solution:

    let topColor = UIColor.blue
    let bottomColor = UIColor.black

    self.tableView.backgroundColor = topColor
    self.tableView.tableFooterView = UIView(frame: CGRect.zero)
    let footerView = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 1000))
    footerView.backgroundColor = bottomColor
    self.tableView.tableFooterView?.addSubview(footerView)

Upvotes: 1

Nikolay Khramchenko
Nikolay Khramchenko

Reputation: 421

I solved this problem with the use of autolayouts. The solution works on different screen sizes and with orientation change.

   self.tableView.tableFooterView = UIView();

   if let tableFooterView = self.tableView.tableFooterView {
         let bigFooterView = UIView();
         bigFooterView.backgroundColor = UIColor.white;
         bigFooterView.isOpaque = true;
         tableFooterView.addSubview(bigFooterView);

         bigFooterView.translatesAutoresizingMaskIntoConstraints = false;

         tableFooterView.addConstraint(NSLayoutConstraint(item: bigFooterView, attribute: .trailing, relatedBy: .equal, toItem: tableFooterView, attribute: .trailing, multiplier: 1, constant: 0));
         tableFooterView.addConstraint(NSLayoutConstraint(item: bigFooterView, attribute: .leading, relatedBy: .equal, toItem: tableFooterView, attribute: .leading, multiplier: 1, constant: 0));
         tableFooterView.addConstraint(NSLayoutConstraint(item: bigFooterView, attribute: .top, relatedBy: .equal, toItem: tableFooterView, attribute: .top, multiplier: 1, constant: 0));
         tableFooterView.addConstraint(NSLayoutConstraint(item: bigFooterView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 1000));
   }

Upvotes: 2

Ivan Smetanin
Ivan Smetanin

Reputation: 2039

Here is the Swift 3 version:

var frame = self.tableView.bounds
frame.origin.y = -frame.size.height
let view = UIView(frame: frame)
view.backgroundColor = .gray
self.tableView.addSubview(view)

Upvotes: 8

Kwan
Kwan

Reputation: 11

I have expanded the answer in Light gray background in “bounce area” of a UITableView to the bottom side as well. Hope this helps :)

CGRect topFrame = self.tableView.bounds;
topFrame.origin.y = -topFrame.size.height;
UIView* topView = [[UIView alloc] initWithFrame:topFrame];
topView.backgroundColor = [UIColor grayColor]; // change to any color you want
[self.tableView addSubview:topView];

CGRect bottomFrame = self.tableView.bounds;
bottomFrame.origin.y = self.tableView.contentSize.height;
UIView* bottomView = [[UIView alloc] initWithFrame:bottomFrame];
bottomView.backgroundColor = [UIColor grayColor]; // change to any color you want
[self.tableView addSubview:bottomView];

Upvotes: 1

danbretl
danbretl

Reputation: 644

The easiest and most lightweight way to solve this problem is:

  1. Set the background color of the table view to whatever you want - in your case, white.
  2. Put the search bar view inside a container view. Set the table view's header view to this container view (instead of the search bar view itself, which is probably what you were doing previously).
  3. In that container view, add another subview with frame equal to a rect like (0, -480, 320, 480), and set the background color of that subview to whatever color you want - in your case, grayish.

That should be all you need to do. I just did this myself and achieved the look I wanted, exactly the same as the Mail app. Using scrollViewDidScroll is a major waste of CPU resources, and subclassing UITableView is super messy, IMO.

Upvotes: 14

lemnar
lemnar

Reputation: 4053

This might not be a "best practice," but if you really want to do it like Apple, there's a private UITableView property called tableHeaderBackgroundColor. The grayish color is #e2e7ed.

You could put something like this in the -viewDidLoad method of a UITableViewController:

UIColor *grayishColor = [UIColor colorWithRed:226/255.0
                                        green:231/255.0
                                         blue:237/255.0 alpha:1.0];
[self.tableView setValue:grayishColor forKey:@"tableHeaderBackgroundColor"];

Upvotes: 3

Alex Pretzlav
Alex Pretzlav

Reputation: 15615

Set the tableFooterView to a view of 0 height and width that draws way outside its bounds. An easy way is to add a big subview to it:

self.tableView.tableFooterView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
UIView *bigFooterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 1000)];
bigFooterView.backgroundColor = [UIColor whiteColor];
bigFooterView.opaque = YES;
[self.tableView.tableFooterView addSubview:bigFooterView];
[bigFooterView release];

adjust [UIColor whiteColor] and the width of your bigFooterView accordingly (if your tableView can go horizontal, you'll want it to be wider than 320). This way at the top you will see whatever your table view background is, and on the bottom whatever you set this view's background to.

Upvotes: 13

Aaron Brethorst
Aaron Brethorst

Reputation: 763

Courtesy of Erica Sadun:

- (void) scrollViewDidScroll: (UIScrollView *) sv
{
    float percent =  sv.contentOffset.y / sv.contentSize.height;
    percent = 0.5 + (MAX(MIN(1.0f, percent), 0.0f) / 2.0f);

    sv.backgroundColor = [UIColor colorWithRed:percent * 0.20392
                                         green:percent * 0.19607
                                          blue:percent * 0.61176 alpha: 1.0f];
}

and then here's the modified version I'm using:

- (void)scrollViewDidScroll:(UIScrollView *)sv
{
        UIColor *backgroundColor = nil;

        float percent = sv.contentOffset.y / sv.contentSize.height;
        percent = 0.5 + (MAX(MIN(1.0f, percent), 0.0f) / 2.0f);

        if (0.5f == percent)
        {
            backgroundColor = RGBCOLOR(233.0f, 235.0f, 237.0f);
        }
        else
        {
            CGFloat r = 233.0f * (1.0f - percent) + 255.0f * percent;
            CGFloat g = 235.0f * (1.0f - percent) + 255.0f * percent;
            CGFloat b = 237.0f * (1.0f - percent) + 255.0f * percent;
            backgroundColor = RGBCOLOR(r,g,b);
        }           
        sv.backgroundColor = backgroundColor;
}

Upvotes: 8

Dutchie432
Dutchie432

Reputation: 29160

I think you just want to set your cell's BG Color to white, and make the table's BG color the other (gray) color. Im not sure you'd have success trying to do that with transparent cells.

Upvotes: -1

Nathan de Vries
Nathan de Vries

Reputation: 15511

You should look into using the tableHeaderView and tableFooterView properties of the UITableView.

Upvotes: -1

Related Questions