Is it possible to disable floating headers in UITableView with UITableViewStylePlain?

135,657

Solution 1

You should be able to fake this by using a custom cell to do your header rows. These will then scroll like any other cell in the table view.

You just need to add some logic in your cellForRowAtIndexPath to return the right cell type when it is a header row.

You'll probably have to manage your sections yourself though, i.e. have everything in one section and fake the headers. (You could also try returning a hidden view for the header view, but I don't know if that will work)

Solution 2

A probably easier way to achieve this:

Objective-C:

CGFloat dummyViewHeight = 40;
UIView *dummyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, dummyViewHeight)];
self.tableView.tableHeaderView = dummyView;
self.tableView.contentInset = UIEdgeInsetsMake(-dummyViewHeight, 0, 0, 0);

Swift:

let dummyViewHeight = CGFloat(40)
self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: dummyViewHeight))
self.tableView.contentInset = UIEdgeInsets(top: -dummyViewHeight, left: 0, bottom: 0, right: 0)

Section headers will now scroll just like any regular cell.

Solution 3

(For who ever got here due to wrong table style) Change Table style from plain to grouped, via the attributes inspector, or via code:

let tableView = UITableView(frame: .zero, style: .grouped)

Solution 4

WARNING: this solution implements a reserved API method. This could prevent the app from being approved by Apple for distribution on the AppStore.

I've described the private methods that turns of section headers floating in my blog

Basically, you just need to subclass UITableView and return NO in two of its methods:

- (BOOL)allowsHeaderViewsToFloat;
- (BOOL)allowsFooterViewsToFloat;

Solution 5

In your Interface Builder click on your problem Table View

problem table view

Then navigate to Attributes Inspector and change Style Plain to Grouped ;) Easy

easy

Share:
135,657

Related videos on Youtube

Tricky
Author by

Tricky

Updated on March 06, 2022

Comments

  • Tricky
    Tricky about 2 years

    I'm using a UITableView to layout content 'pages'. I'm using the headers of the table view to layout certain images etc. and I'd prefer it if they didn't float but stayed static as they do when the style is set to UITableViewStyleGrouped.

    Other then using UITableViewStyleGrouped, is there a way to do this? I'd like to avoid using grouped as it adds a margin down all my cells and requires disabling of the background view for each of the cells. I'd like full control of my layout. Ideally they'd be a "UITableViewStyleBareBones", but I didn't see that option in the docs...

    Many thanks,

    • Fattie
      Fattie over 10 years
    • average Joe
      average Joe over 9 years
      Use table style UITableViewStyleGrouped - this is the answer for all who are looking for disabling floating headers and don't read the whole question (it happened to me...).
    • Lee Fastenau
      Lee Fastenau about 9 years
      @Kasztan This is a zero line solution that works great! Thanks.
    • Mr. Míng
      Mr. Míng about 3 years
      Using empty sections is also a great choice stackoverflow.com/a/8350326/456536
  • Tricky
    Tricky almost 15 years
    Yeah... it seems a bit of a hack though. This seems like an oversight an Apple's part, as clearly the code is there to do it, we just need to be able to set a flag.
  • Daniel Wood
    Daniel Wood almost 14 years
    This doesn't answer the question. Tricky is referring to the titleHeaderViews which are the views that sit between the cells, not the table header view which is what you seem to be suggesting.
  • jemmons
    jemmons almost 14 years
    The original poster doesn't want a custom header. They want a header that doesn't "float" at the top of the table. Your suggestion still floats.
  • jemmons
    jemmons almost 14 years
    An answer doesn't deserve a downvote just because it references private APIs (not everybody is writing code to be submitted to the AppStore). This is doubly true when the answer happens to be correct. Subclassing (or, more easily, making a UITableView category) that returns NO for these methods stops headers from floating. If you'd like to see this added as a public API, please file a bug report: bugreport.apple.com
  • Javier Soto
    Javier Soto over 12 years
    If we implement that function in an App, how would Apple realize you're using a private API? From all they know, I just implemented a method in a subclass of UITableView, and they can't even see that without de-assembling the code, and it wouldn't be so easy. It's not CALLING a method in a private API, it's just implementing one....
  • Steve Moser
    Steve Moser over 12 years
    Great idea. I love this hack.
  • Layynezz
    Layynezz about 12 years
    This should be the top answer. There is a blog post about it here: corecocoa.wordpress.com/2011/09/17/…
  • Shyam Bhat
    Shyam Bhat almost 12 years
    This friggin works like a charm!! The presence of a table header view header stops the section headers from floating. And an invisible header with appropriate content insets for the table does the trick .. Thank you so much! wonder why this answer's not getting much attention
  • Shyam Bhat
    Shyam Bhat almost 12 years
    Still don't believe it! No private APIs, no digging into the classes, nothing! I have been facing this problem for ages and have been adding tableviews on top of scroll views (with the tableview scroll disabled), which would make the table headers scroll normally. but just started to search if apple's provided any new methods lately to fix this.. so glad i stumbled upon your answer. thanks again
  • Shyam Bhat
    Shyam Bhat almost 12 years
    kinda funny. appreciate the idea, but a hack is a hack. the headers would start floating at the bottom so doesn't really solve the problem
  • gsempe
    gsempe over 11 years
    This solution do not really work. I keep getting an extra space around at the around cells. Any idea ?
  • Sebastian Łuczak
    Sebastian Łuczak over 11 years
    You saved my day with this little thing. Works as expected without single line of code. I'm amazed. Thank You Sir!
  • whyoz
    whyoz over 11 years
    Yeah, I just returned a UILabel in viewForHeaderInSection with the same height as the dragged UIView and set the contentInset to the same negative height, and blammo...samvermette, you're a saver mate!
  • Piotr Tomasik
    Piotr Tomasik over 11 years
    Wouldn't the contentView of the cells still be shifted to the right?
  • Piotr Tomasik
    Piotr Tomasik over 11 years
    Stumbled upon this solution as well... But really thinking about it, isn't it just taking advantage of a bug? Ideally the contentInset should also inset the point at which the headers scroll. Apple still hasn't patched it 2 years later!
  • Ruzard
    Ruzard over 11 years
    the only drawback I saw is that top header will not be shown anymore (you can see it only through scrolling up). At least for me it is not shown
  • Joel Martinez
    Joel Martinez over 11 years
    Unfortunately, I'm seeing the same behavior as @Ruzard.
  • makdad
    makdad over 11 years
    This isn't for a section, this is for 1 header at the top.
  • anemo
    anemo over 11 years
    Implemented 'willSelectRowAtIndexPath' so that the control never reaches 'didSelectRowAtIndexPath' on selecting the Section Header row.
  • Yariv Nissim
    Yariv Nissim over 11 years
    Actually, I fold + unfold the rows when the header is selected. But good to know you can do that
  • onekiloparsec
    onekiloparsec over 11 years
    This solutions worked well for me. Apparently, here's another one completely different: stackoverflow.com/a/3984585/707984
  • Vilém Kurz
    Vilém Kurz about 11 years
    you can make the original top table view header appear by raising its height by 100. This cancels out content inset setting influence on header, but still allows disabling floating headers.
  • Stavash
    Stavash almost 11 years
    Another drawback: This completely confuses any index bar you might have considered using.
  • nonamelive
    nonamelive almost 11 years
    Has anyone used this method and got approved in the App Store?
  • jhabbott
    jhabbott almost 11 years
    I got this working in code with: self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 24)]; and setting the content-inset-top to -24 in IB. How do you "Drag a UIView onto your TableView to make it its header view." in IB? There is no outlet for the tableHeaderView property.
  • anemo
    anemo almost 11 years
    Private Methods! be wary, the app will get rejected. Check my answer below for the correct way to achieve the effect
  • anemo
    anemo almost 11 years
    Check my answer below for the correct way to achieve the effect without any special hack, just manage the first cell of every section as its section header!
  • Shyam Bhat
    Shyam Bhat almost 11 years
    You can still show the tableHeaderView of the table by increasing it's height on the top, by a number equal to the height of section header and reduce the content inset by the same number.
  • Glenn85
    Glenn85 almost 11 years
    Great answer, but why the 'if (indexPath.row != 0)' check in 'didSelectRowAtIndexPath'? Is it just to be extra secure? The row can never be 0 with your 'willSelectRowAtIndexPath' implementation, right?
  • kas-kad
    kas-kad over 10 years
    @jemmons if you don't want me to downvote your answer mark it as "private API is used here". Sort of disclaimer :)
  • anemo
    anemo over 10 years
    @Glenn85, Sorry for the late reply. Yes it is just for an extra security.
  • lucaslt89
    lucaslt89 about 10 years
    you deserve heaven buddy...worked like a charm! i can't believe Apple doesn't provide a property to set this so typical behaviour...
  • mskw
    mskw about 10 years
    change the tableview to UITableViewStyleGrouped with viewforheader, then it will make it stop
  • MartinMoizard
    MartinMoizard about 10 years
    Your "my blog" link is broken
  • hasan
    hasan about 9 years
    Do you mean return NO?!
  • iDevAmit
    iDevAmit about 9 years
    Great!! This solution saved my time.
  • aryaxt
    aryaxt almost 9 years
    @jemmons "not everybody is writing code to be submitted to the AppStore" Appstore is not really the problem. The problem is apple can change the private APIs without communicating or deprecating which will break your app. That's a better reason on why you shouldn't use private APIs than getting rejected by Apple
  • deepax11
    deepax11 over 8 years
    It's old post but could not stop my self to write this. Awesome! Thanks.
  • Eric Smith
    Eric Smith over 8 years
    Perfect! This is just what I needed
  • cohen72
    cohen72 over 8 years
    David, This is an excellent answer! You can also use the 72 names and meditate on ayin resh yud :)
  • Balazs Nemeth
    Balazs Nemeth about 8 years
    I cannot increase this enough time!
  • Michael Peterson
    Michael Peterson about 8 years
    "Other then using UITableViewStyleGrouped, is there a way to do this?"
  • NSGangster
    NSGangster about 8 years
    For me I had to use positive dummy height for my inset but This helped a ton!
  • Saurabh Bhatia
    Saurabh Bhatia almost 8 years
    Thank you @david72, your answer has turned out to be the most accurate one.
  • Ell Neal
    Ell Neal over 7 years
    I wish I could upvote this again, I'm fairly certain this is at least the third time I've ended up on this question and this has solved my problem.
  • Mark A. Donohoe
    Mark A. Donohoe over 7 years
    FooterViews do float, just like HeaderViews. They just float at the bottom of the screen, not top.
  • Tung Fam
    Tung Fam over 7 years
    Good thing i learned to check all the answers before implementing the most upvoted one :)
  • ostap_holub
    ostap_holub over 6 years
    Guys, be aware of using this method with Swift 4. Default settings of Swift 4 project in Xcode 9 has @objc inference property disabled. So, you should to mark these methods like @objc manually otherwise it will lead to undefined behavior. Hope, this tip can help you.
  • Cristian Holdunu
    Cristian Holdunu over 6 years
    Now this guys, is the answer you were looking for. Be aware that you can find the TableView Style property in the AttributesInspector as well.
  • lennartk
    lennartk almost 6 years
    These are the kind of workarounds that I just laugh at, it feels so bad doing this but I love it. Thank you man
  • Buglinjo
    Buglinjo over 5 years
    You saved my day! Thanks!
  • Pomme2Poule
    Pomme2Poule over 5 years
    I've found this solution super hacky. It doesn't work well if your headers can vary in size (like when you support dynamic type). 😕
  • Ferdz
    Ferdz over 5 years
    The question specifically mentions to look for a way "Other then using UITableViewStyleGrouped"
  • COSMO BAKER
    COSMO BAKER over 5 years
    It's also in the attributes inspector in IB.
  • MQoder
    MQoder about 5 years
    Please, don't do that🙏
  • Jason
    Jason over 4 years
    If you want the grouped table to look like the plain table, change the heightForHeader and Footer to return 0.1 (returning 0 will use the default value instead)
  • Daniel
    Daniel over 4 years
    This does not work with a refresh control. The control will be off screen.
  • Ilias Karim
    Ilias Karim over 4 years
    You can return 0 instead of .leastNormalMagnitude. Also you need to implement tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView?
  • Tamás Sengel
    Tamás Sengel over 4 years
    @IliasKarim Setting it to 0 casues it to have a non-zero height. Also, it's not necessary to implement the viewForFooterInSection function in this case.
  • Ilias Karim
    Ilias Karim over 4 years
    0 and .leastNormalMagnitude had the same effect. Implementing the viewForFooterSection method is necessary. You should return nil. This is on Swift 5.1 with Xcode 11.3.1.
  • Nikola Markovic
    Nikola Markovic over 3 years
    ☝️ This should be marked as correct answer. Also, for storyboard lovers, you have this property in storyboard Attribute inspector when you select your UITableView
  • Mr. Míng
    Mr. Míng about 3 years
    Great answer! But, grouped table view has different separators for the first and last cell of every section, which may be you don't like.
  • Farhandika
    Farhandika over 2 years
    a huge thank you mate, your answer satisfy what I need so far, best of luck to you
  • Zin Win Htet
    Zin Win Htet over 2 years
    how about for Swift?