Is it possible to disable floating headers in UITableView with UITableViewStylePlain?
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
Then navigate to Attributes Inspector and change Style Plain to Grouped ;) Easy
Related videos on Youtube
Tricky
Updated on March 06, 2022Comments
-
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 toUITableViewStyleGrouped
.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 over 10 years
-
average Joe over 9 yearsUse 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 about 9 years@Kasztan This is a zero line solution that works great! Thanks.
-
Mr. Míng about 3 yearsUsing empty sections is also a great choice stackoverflow.com/a/8350326/456536
-
-
Tricky almost 15 yearsYeah... 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 almost 14 yearsThis 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 almost 14 yearsThe 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 almost 14 yearsAn 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 over 12 yearsIf 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 over 12 yearsGreat idea. I love this hack.
-
Layynezz about 12 yearsThis should be the top answer. There is a blog post about it here: corecocoa.wordpress.com/2011/09/17/…
-
Shyam Bhat almost 12 yearsThis 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 almost 12 yearsStill 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 almost 12 yearskinda 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 over 11 yearsThis solution do not really work. I keep getting an extra space around at the around cells. Any idea ?
-
Sebastian Łuczak over 11 yearsYou saved my day with this little thing. Works as expected without single line of code. I'm amazed. Thank You Sir!
-
whyoz over 11 yearsYeah, 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 over 11 yearsWouldn't the contentView of the cells still be shifted to the right?
-
Piotr Tomasik over 11 yearsStumbled 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 over 11 yearsthe 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 over 11 yearsUnfortunately, I'm seeing the same behavior as @Ruzard.
-
makdad over 11 yearsThis isn't for a section, this is for 1 header at the top.
-
anemo over 11 yearsImplemented 'willSelectRowAtIndexPath' so that the control never reaches 'didSelectRowAtIndexPath' on selecting the Section Header row.
-
Yariv Nissim over 11 yearsActually, I fold + unfold the rows when the header is selected. But good to know you can do that
-
onekiloparsec over 11 yearsThis solutions worked well for me. Apparently, here's another one completely different: stackoverflow.com/a/3984585/707984
-
Vilém Kurz about 11 yearsyou 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 almost 11 yearsAnother drawback: This completely confuses any index bar you might have considered using.
-
nonamelive almost 11 yearsHas anyone used this method and got approved in the App Store?
-
jhabbott almost 11 yearsI 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 thetableHeaderView
property. -
anemo almost 11 yearsPrivate Methods! be wary, the app will get rejected. Check my answer below for the correct way to achieve the effect
-
anemo almost 11 yearsCheck 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 almost 11 yearsYou 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 almost 11 yearsGreat 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 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 over 10 years@Glenn85, Sorry for the late reply. Yes it is just for an extra security.
-
lucaslt89 about 10 yearsyou deserve heaven buddy...worked like a charm! i can't believe Apple doesn't provide a property to set this so typical behaviour...
-
mskw about 10 yearschange the tableview to UITableViewStyleGrouped with viewforheader, then it will make it stop
-
MartinMoizard about 10 yearsYour "my blog" link is broken
-
hasan about 9 yearsDo you mean return NO?!
-
iDevAmit about 9 yearsGreat!! This solution saved my time.
-
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 over 8 yearsIt's old post but could not stop my self to write this. Awesome! Thanks.
-
Eric Smith over 8 yearsPerfect! This is just what I needed
-
cohen72 over 8 yearsDavid, This is an excellent answer! You can also use the 72 names and meditate on ayin resh yud :)
-
Balazs Nemeth about 8 yearsI cannot increase this enough time!
-
Michael Peterson about 8 years"Other then using UITableViewStyleGrouped, is there a way to do this?"
-
NSGangster about 8 yearsFor me I had to use positive dummy height for my inset but This helped a ton!
-
Saurabh Bhatia almost 8 yearsThank you @david72, your answer has turned out to be the most accurate one.
-
Ell Neal over 7 yearsI 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 over 7 yearsFooterViews do float, just like HeaderViews. They just float at the bottom of the screen, not top.
-
Tung Fam over 7 yearsGood thing i learned to check all the answers before implementing the most upvoted one :)
-
ostap_holub over 6 yearsGuys, 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 over 6 yearsNow 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 almost 6 yearsThese are the kind of workarounds that I just laugh at, it feels so bad doing this but I love it. Thank you man
-
Buglinjo over 5 yearsYou saved my day! Thanks!
-
Pomme2Poule over 5 yearsI'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 over 5 yearsThe question specifically mentions to look for a way "Other then using UITableViewStyleGrouped"
-
COSMO BAKER over 5 yearsIt's also in the attributes inspector in IB.
-
MQoder about 5 yearsPlease, don't do that🙏
-
Jason over 4 yearsIf 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 over 4 yearsThis does not work with a refresh control. The control will be off screen.
-
Ilias Karim over 4 yearsYou can return 0 instead of
.leastNormalMagnitude
. Also you need to implementtableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView?
-
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 over 4 years
0
and.leastNormalMagnitude
had the same effect. Implementing theviewForFooterSection
method is necessary. You should return nil. This is on Swift 5.1 with Xcode 11.3.1. -
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 about 3 yearsGreat 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 over 2 yearsa huge thank you mate, your answer satisfy what I need so far, best of luck to you
-
Zin Win Htet over 2 yearshow about for Swift?