How to remove UITableView section header separator - ios

I would like to remove (or make them clearColor) UITableView's section header separators. Setting tableView.separatorStyle = .none doesn't work. I've also tried solutions from here, but none of them actually worked for me (maybe because the answers are pretty old). I still get this tiny separator below the section header.
I created the UITableView in Storyboard and add a UITableViewCell there. Then I set it as a header like this:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: "headerTableViewCell")
return cell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if section == 1 {
return 49
}
return 0
}

Don't know why you are returning UITableViewCell in viewForHeaderInSection method so may be it is possible that is showing separator of that UITableViewCell. Try returning the contentView of cell instead of cell from viewForHeaderInSection method.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: "headerTableViewCell")
return cell.contentView
}

Try this:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
headerView.backgroundColor = UIColor.clear
return headerView
}

I have solved this by following way:
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 0.01
}

Turns out overriding layoutSubviews removes all the cell's separators, both section-related and cell-related.
#interface MyCustomCell : UITableViewCell
#end
#implementation MyCustomCell
- (void)layoutSubviews {
// don't call [super layoutSubviews]
// can be left empty
// does not harm other UI elements inside the contentView
}
#end
In multiple-cell sections, you may just want to only remove the Section-related separators (at the top of first cell and at the bottom of last cell), keeping inset, inter-cell, separators shown:
- (void)layoutSubviews {
[super layoutSubviews];
for (UIView *view in self.subviews) {
if ([view isEqual:self.contentView]) continue;
view.hidden = view.bounds.size.width == self.bounds.size.width;
}
}

Related

How to show and hide Custom UITableView Header Cell of Table View in Swift3 iOS

I am developing an application in Swift3 where I have to show and hide UITableView Header for different users. For displaying UITableView Header View, I have created a custom class CustomHeaderCell of UITableViewCell.
Here is my code:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 235.0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell") as! CustomHeaderCell
return headerCell
}
Now Can anyone please help me to hide this Header of my UITableView?
Note: I tried using this tableView.tableHeaderView?.isHidden = true, but not working. Should I need to do the validation in heightForHeaderInSection?
Reference Link to Add HeaderViewCell: http://www.accella.net/knowledgebase/custom-header-and-footer-views-for-uitableviews/
If you have a way to differentiate users then you can just change the header height like this
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if userA {
return 235.0
} else {
return 0
}
}
That should help in hiding the header
You are mixing tableHeaderView and section header views, which are differents:
tableHeaderView is a view showed as a header for the whole UITableView
section header views are reusable views used for displaying header above each section
In your case, you want to use section header views, so you should return empty ones for non concerned users (I assume here sectionNeedHeader will be replaced by your condition).
Also, you better use UITableViewHeaderFooterView instead of UITableViewCell. The behavior is globally the same but it's made for this usage:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if sectionNeedHeader {
return 235.0
}
return 0.0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if sectionNeedHeader {
let headerCell = tableView.dequeueReusableHeaderFooterView(withIdentifier: "HeaderView") as! CustomHeaderView
return headerView
}
return nil
}

Resize a UITableView Header without autolayout

Is it possible to resize a UITabeView Header after the text is set to it?
In my xib I got a TableView with a header with a height of 42 for 1 line of text. For 2 lines I need a height of 52 and for 3 I need 62. The title is set dynamically to the header. But the heightForHeaderInSection func is called before the header text is set by the Lifecycle. So maybe lines 2 & 3 are not shown.
I wrote a method which tells me how many lines of text the header got but how to update the header? if i call tableView.reloadData() I end up in an infinity loop. And if I set var for every lineamoun
t I found the heightForheaderInSection is never called.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: headerCell) as! SectionHeader
cell.titleLabel.text = self.sectionTitle
linesOfHeader = cell.getNumberOfLines()
return cell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if(linesOfHeader == 1) { return 44}
else if(linesOfHeader == 2) {return 52}
else { return 62}
}
a better solution to support dynamic header height is using "UITableViewAutomaticDimension" like this:
In viewDidLoad add these lines:
self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension
self.tableView.estimatedSectionHeaderHeight = 50
and remove the function heightForHeaderInSection
Then allow the label to extend to the required number of lines
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: headerCell) as! SectionHeader
cell.titleLabel.text = self.sectionTitle
cell.titleLabel.numberOfLines = 3
return cell
}
if the header height overlap the cells height as well add these two lines to viewDidLoad
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 40 // estimated cell height

Autosizing UITableView inside custom UIView for section

I have created UIViewController and added UITableView on it (pinned to all four edges with autolayout).
Then I set estimatedRowHeight (44) and rowHeight (UITableViewAutomaticDimension) and returned 5 custom cells. And it worked.
Now, I want to add custom UITableViewHeaderFooterView that would have dynamic height.
I'm doing next:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 88.0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return R.nib.orderStatusHeaderView.firstView(owner: self)!
}
My OrderStatusHeaderView is a xib view that has UITableView on it pinned to all 4 edges with autolayout.
OrderStatusHeaderView:
final class OrderStatusHeaderView: UITableViewHeaderFooterView {
#IBOutlet weak var tableView: UITableView! {
didSet {
tableView.dataSource = self
tableView.delegate = self
tableView.rowHeight = 44.0
}
}
}
extension OrderStatusHeaderView: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "\(indexPath.row)")
cell.textLabel?.text = "\(indexPath.row)"
cell.backgroundColor = .red
return cell
}
}
This displays like:
And when I tap or scroll, all red cells disappears. What could it be? And how to make UITableView dynamically load content and UITableViewHeaderFooterView will size itself so it fit UITableView.contentSize. Is it possible?
Check out:
tableView(_:estimatedHeightForFooterInSection:)
and
tableView(_:heightForFooterInSection:)
You also have the equilavant for headerInSection.
Since you are asking for a table's header and footer view, you can skip the delegate methods you describe. Those (as the name implies) are for SECTION headers and footers.
When you set a view that is using AutoLayout as the table's header or footer, the its frame still has a zero height (That's why buttons in such view for example won't work as they are not receiving the touches).
To correctly size a table's header or footer views using AutoLayout you have to apply a trick to actually calculate the height yourself, and set the headerView again. It is described in detail in many posts like these:
https://stackoverflow.com/a/28102157/756039
https://gist.github.com/marcoarment/1105553afba6b4900c10
http://collindonnell.com/2015/09/29/dynamically-sized-table-view-header-or-footer-using-auto-layout/
http://roadfiresoftware.com/2015/05/how-to-size-a-table-header-view-using-auto-layout-in-interface-builder/
Hope this helps.

heightForHeaderInSection only called once

Coding in Swift 3. Have a tableView with custom cells and header.
I have a tableView with custom cells and headers. The headers have two (2) labels in them and have dynamic cell heights since the labels may be long. My problem is the first time the tableView and sections are configured the label appears as it should, HOWEVER, after scrolling down and then back up the headers' layout somehow breaks.
As you can see below, after I scroll down then back up to the cells, the label is getting cutoff.
After printing out what methods are being called I found that the first time scrolling down the tableView the following two (2) override functions are called.
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
print("\(section) heightForHeaderInSection")
print("\(section) returning AUTO for header")
return UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
print("\(section) viewForHeaderInSection")
let header = tableView.dequeueReusableCell(withIdentifier: "QuestionHeader") as! QuestionHeader
header.delegate = self
header.contentView.backgroundColor = UIColor.groupTableViewBackground
header.questionTextLabel.text = String(questionStringArray[section])
header.questionNumberLabel.text = (String(section + 1) + ")")
return header.contentView
}
But when i scroll back up ONLY the viewForHeader function is called and I think because the height is no longer being set to UITableViewAutomaticDimension the labels get cutoff?
Any ideas?
You should return header instead of header.contentView from tableView: viewForHeaderInSection: method:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = tableView.dequeueReusableCell(...
...
return header
}

Space Between Sections in UITableview

I need to reduce the space between two sections ofUITableView. I looked at this question but the solution doesn't allow for my custom header view because it combines the space of the footer and header.
Here is a picture of the UITableView. The black color is the UITableView background color.
On iOS 15 you may want to reduce the sectionHeaderTopPadding
if #available(iOS 15.0, *) {
tableView.sectionHeaderTopPadding = 0
}
Did you try override this function:
override func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return .leastNormalMagnitude
}
I think you can solve this by adjusting the footer view height to its min: in Storyboard or XIB.
I don't know what you have written in your code for footer height. Sorry if I am wrong.
Possible duplicate of Hide footer view in UITableView
For Swift 4+ you need to implement these two methods
extension MyViewController : UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return CGFloat.leastNormalMagnitude
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return UIView()
}
}
For Swift 3
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return CGFloat.leastNormalMagnitude
}
For Swift 5+:
There is some space for the headers and footers by default. That's why I was having the problem of setting an exact separation for the sections.
My solution to having a separation between 2 sections is the following:
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if section == 0 {
return 24
} else if section == 1 {
return 32
} else {
return 40
}
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
nil
}
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
nil
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
CGFloat.leastNormalMagnitude
}
As you see for viewForFooterInSection and viewForHeaderInSection I needed to return nil.
In case you only want to change the footerHeight, just return CGFloat.leastNormalMagnitude for heightForHeaderInSection, and return the heights for each section in heightForFooterInSection.
Along with the answer posted by Icaro I would like to add that you also need to implement the tableView:viewForFooterInSection: method returning nil for the section you want to remove the empty space below
It will then become:
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0.001f;
}
-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return nil;
}
You need to use the method heightForHeaderInSection for defining the space between header & cell text. You can also change it depending on different sections for eg. at some sections you may need to show more distance & under some, you don't want to show gap. For such case you can use CGFLOAT_MIN which is 0.000001f. Giving you an example, how you can use different section with different header heights:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if (section == 0 || section == 2)
{
return 55.0;
}
else
{
return CGFLOAT_MIN;
}
}
This also may help :
override func viewDidLoad() {
super.viewDidLoad()
tableView.sectionHeaderHeight = UITableViewAutomaticDimension
}
Select the tableView in your storyboard/objectCode and ensure that the style is set to Plain, instead of Grouped. You can find this setting in the attributes "Inspector" tab.
let myTableView : UITableView = {
let tableView = UITableView(frame: .zero, style: .plain)
tableView.register(TableCellClass.self, forCellReuseIdentifier: "cellId")
tableView.backgroundColor = UIColor(red: 123/255, green: 190/255, blue: 120/255, alpha: 1)
tableView.separatorStyle = .none
tableView.translatesAutoresizingMaskIntoConstraints = false
return tableView
}()
In Xcode 13.2, you can adjust the height of the header and footer of sections in the storyboard - see screenshot below:
TableView Delegate methods doesn't effect with float value is 0.0f. Try giving a value greater than that.
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0.00001f;
}
- (UIView*)tableView:(UITableView*)tableView
viewForFooterInSection:(NSInteger)section {
return [[UIView alloc] initWithFrame:CGRectZero];
}
Rather than implementing the UITableViewDelegate methods and defining the sectionFooterHeight via CGFloat.leastNormalMagnitude, one can alternatively just
tableView.sectionFooterHeight = 0
and the spacing between sections while no footer is present will go away.
The mechanism is that by default this value is set to UITableView.automaticDimension.
As long as
it stays UITableView.automaticDimension
there are no delegate/dataSource methods that implement the configuration of footer i.e. titleForFooterInSection/viewForFooterInSection
table view's style is set to .grouped
then UITableView will deliberately insert a spacing between sections with no view.
You change sectionFooterHeight to 0, the magic goes away.
I just simply had to reduce the top padding for the tableview section header:
tableView.sectionHeaderTopPadding = 0
You can do it by implement the delegate heightForHeaderInSection & heightForFooterInSection.
The return vaule should not be 0, even if the SectionHeader or the height of SectionFooter is 0, it need a very small value, try CGFLOAT_MIN.
for my example:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
if (section == [self.dataArray indexOfObject:self.bannerList]) {
return 46;
}
return CGFLOAT_MIN;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return CGFLOAT_MIN;
}
Work for me
tableView.sectionFooterHeight = 10
// ...
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return nil
}
swift 5 iOS 15
self.tableView.estimatedSectionFooterHeight = 16.0 // spacing between Sections

Resources