I'm trying to apply a size on my UITableView headerView but it seems like the first section header always is a bit smaller than the rest section headerViews. I've said the constraints for the UITableView so it should be fine. How come the first section is smaller?
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return ""
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 20
}
This behavior occurs when using a Grouped UITableView. The section header height appears shorter for the first section header, because it doesn't have a footer above of it. However, every section header after the first one, does have a footer directly above it. The footers have a default height, which is contributing to the overall height appearance of the section header. Therefore, set the section footer heights so the space between the group sections will have the same visual height.
override func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return CGFloat.min
}
We use CGFloat.min instead of 0, because returning 0 will cause the footer to return a default height.
Related
I am using UITableView grouped and using multiple sections. I am using these codes to hide the footer for sections.
self.tableView.estimatedSectionFooterHeight = 0
self.tableView.sectionFooterHeight = 0
public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 0.0
}
public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return UIView()
}
Only Footer for section 0 is not getting hidden.
Here is the screenshot:
Please help!
If you are using grouped tableview then there will be footer always and it never accepts 0 value. But you can return 0.5 or 1 to fix your problem and no need to override viewForFooterInSection
Sorry guys to bother, what I have done is I was also hiding sections and header which don't have any rows.
So one of the header was not getting hidden as I was returning empty UIView() in viewForHeaderInSection. Though I was returning 0 in heightForHeaderInSection for sections which don't have rows.
The problem is now solved as I am returning nil in viewForHeaderInSection.
Screenshot:
I am trying to have headers in my grouped tableView but not footers. I am creating headers with:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "Header") as! DateHeaderTableViewHeaderFooterView
...
return headerView
}
I have setup the tableView in storyboard to use automatic dimensions for all cells and headers and footers.
I assumed because I didn't provide any footers, they would not exist however footers are being added to each section. Also all the headers and footers have a gray background.
I tried unchecking the footer automatic dimension and selecting a value however the lowest value it can accept is 1 and still the footer shows up.
How can I have headers but not footers and change the background color of the header?
I can achieve what I want using a plain tableView however the headers are pinned to the top which I am trying to avoid.
You need to implement the following method:
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return CGFloat.leastNormalMagnitude
}
For Xcode 13 + iOS 15 device
You have to set UITableView.sectionHeaderTopPadding to zero also.
if #available(iOS 15.0, *) {
tableView.sectionHeaderTopPadding = 0
}
reference: https://developer.apple.com/forums/thread/683431
I am running into an issue with automatic/dynamic UITableView section header views that contain a UILabel that wraps (numberOfLines = 0). The height is not being calculated properly, especially once you scroll the table and the views are reused. Sometimes the UILabel wraps, sometimes it is truncated, sometimes one or more of the labels are not visible, and sometimes there is extra spacing between the labels. The custom view contains a vertical UIStackView with three UILabels, once of which wraps.
A complete sample app demonstrating the issue can be found at https://github.com/outerstorm/tableviewHeaderTest.
The section header heights are set to automatic in viewDidLoad with the following:
tableView.sectionHeaderHeight = UITableViewAutomaticDimension
tableView.estimatedSectionHeaderHeight = 30.0
and also have implemented the following heightForHeaderInSection just to try to get it to work:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UITableViewAutomaticDimension
}
I have also tried calling setNeedsLayout() and layoutIfNeeded() at various points to no avail. Any suggestions would be greatly appreciated.
Below is a screenshot of the behavior seen in the app. The first section is cutoff and the second section is too tall:
I have faced this kind of issue recently.
I solved it by setting preferredMaxLayoutWidth of multiline labels, i.e.
Before setting the value in labels, set their preferredMaxLayoutWidth as:
self.label1.preferredMaxLayoutWidth = self.label1.frame.size.width
self.label2.preferredMaxLayoutWidth = self.label2.frame.size.width
self.label3.preferredMaxLayoutWidth = self.label3.frame.size.width
Just add estimatedHeightForHeaderInSection function and return your estimated height. It will resolve your issue. Download your modified project from here
func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat
{
return 30;
}
In general
heightForHeaderInSection
always called before
viewForHeaderInSection
when using UITableViewAutomaticDimension, sectionheader height will only calculate once unless called tableview.reloadData() manually.
In the code, you change sectionheader text everytime. the height was calculate at the first time, and doesnt change automatic.
you can change setup func to:
func setup(someNum: Int) {
let text = String(repeating: "This is where the really long text goes so that it will wrap lines appropriately", count: someNum)
mainLabel.text = text
}
and pass the section index to the function
A workaround can be hold the header views in array and then return the height of view from estimated height method
for _ in 0 ..< data.count {
let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: "CustomHeaderView") as! CustomHeaderView
view.setup()
headerViews.append(view)
}
func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat
{
let view = headerViews[section] as? UIView
return (view?.frame.size.height)!
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return headerViews[section] as? UIView
}
From the code's documentation:
// tableView:titleForHeaderInSection: or tableView:titleForFooterInSection: if the title is not nil.
In other words. UITableViewAutomaticDimension is only intended for use if you are providing a section title using titleForHeaderInSection or titleForFooterInSection
Add
self.label1.preferredMaxLayoutWidth = self.label1.frame.size.width
self.label1.numberoflines = 0;
self.label1.linebreakmode = NSLineBreakByWordWrapping;
in awakeFromNib method
or
Kindly check this once
Im trying to implement a tableview that has cells with a product image on the left side and a listing of various product details such as price, title, etc. to the right of the image, however, I have been having trouble with setting up the appropriate spacing/padding between the cells. I want each cell to have some white space between them. Here is an image showing what i have so far, and what the issue is.
TableView
I am using a stackview as a container for the labels with the product details, and am implementing the dynamic row height feature:
self.tableView.rowHeight = UITableViewAutomaticDimension
Everything seems to work great except wajjhen the stackview height is smaller than the imageview height. I can't get the spacing to show in that scenario. I have tried everything for the past 2 days, and it is driving me crazy. Take it easy on me guys as I am an Android guy :)
All I want is for the I want the separators of tableview cells to have a bit of space between either the top and bottom of the imageview or the stackview(whichever is taller/higher).
I have attached a SS of the storyboard to show the layouts and constraints. Please let me know if any more information is need.
Storyboard
for adding consitent spacing to your cell better way is to treat your each item as a section because you can set spacing easily between sections by creating a header view between section.
So logically if you have 10 objects than you will be having 10 section with each section have only one row.
1.Each section with only one row
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
2.Number of section is equal to count array of items
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return array.count
}
3.Set Hieght for spacing/header view
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 10
}
4.create your header view and customise it
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if let view = view as? UITableViewHeaderFooterView{
view.backgroundView?.backgroundColor = UIColor.clearColor()
}
}
Assuming that you have no problem with setting the appropriate height for each cell (if you have, you might want to check this Q&A), I suggest to let each cell on a section instead adding them in the same one.
Technique:
By default, if you are not implementing numberOfSections(in:), it returns 1. You should:
implement it and let it returns the number of array data source -for example- (instead of doing it in tableView(_:numberOfRowsInSection:)).
Let tableView(_:numberOfRowsInSection:) returns 1. Each section will has only one cell.
After that, the trick is to add a header view for the sections (with a clear background color) with desired height, the height will be the margin between the section (cells in your case). You should achieve this by implementing:
tableView(:viewForHeaderInSection:) and tableView(:heightForHeaderInSection:).
The code will be similar to:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
// ...
// MARK:- UITableViewDataSource
func numberOfSections(in tableView: UITableView) -> Int {
return dataSource.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell-ID")
// note that you should read from 'indexPath.section' instead of 'indexPath.row'
let currentObejct = dataSource[indexPath.section]
}
// MARK:- UITableViewDelegate
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
// here, you can customize the header
// or your case want to let it clear...
let margin = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 20.0))
margin.backgroundColor = UIColor.clear
return margin
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 20.0
}
// ...
}
Hope this helped.
You can try giving the Fruit Image a top and a bottom constraint but they must be >= so it doesn't mess your auto layout
And your constraints will probably look like this
3 days later, I finally found a solution I am content with, albeit it is quite janky, but at this point(3 days of dealing with this issue), I don;t really care. I am posting my solutuion in case it helps anyone in the future.
I ended up pinning a view to the tableviewcell with a minimum height of 130 to contain the imageview and stackview. Since I know the minimum height of the tableviewcells is 120, 130 gave a padding of 5 on the top and bottom. I attached the screenshot of my storyboard:
Storyboard
TableView
I have a UITableView in the storyboard with also a header and a footer defined as can be seen in the picture.
However, the header disappears when I move the cell (it seems the header is the top cell). Same thing with the footer. It appears after I have browsed through all cells.
I tried to move the header and the footer outside of the Cell hierarchy. But this resulted in being not visible any more.
How can I make the header and footer sticky?
Don't confuse the section header and footer with the table header and footer.
The section header and footer, in a non-grouped table, are pinned to the top and bottom of the table while you scroll.
But the table header and footer, as you rightly say, are sort of like cells: they are before the first section and after the last section, and they scroll with the table.
If that's not what you want — that is, if there is something you want to show above the table and below the table, all the time — then you need to put them above and below the table view as completely separate views:
thing above
table
thing below
Of course, if you do that, you can't use a UITableViewController. You'll have to have a normal view controller, with the table view as an embedded view and the table view controller as a child view controller.
When using static UITableViews, you can't add custom views as header. You need to set the header and footer like this:
//Header
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
//return your custom view here
}
//Footer
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
//return your custom view here
}
You also have to specify the height of your header/footer:
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
//return the height
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
//return the height
}