Let UIImageView in header section of UITableView overlap the content cells - ios

I would like to have a header section in a table view with a logo and name. Now, I want the logo to overlap the image in the content cell below. I have attached an example of this below :-
Heres what I've tried so far, I've tried to make the header section half the size of (logo + upper and lower padding) -- this just cuts the logo in half
I also tried clipToBounds :-
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 33.0
}
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCellWithIdentifier("headerCell") as! FeedTableViewHeaderCell
cell.designerNameLabel.text = "Vitamin A"
cell.designerLogoImageView.image = UIImage(named: "zeko_small")
cell.designerLogoImageView.clipsToBounds = false
cell.contentView.clipsToBounds = false
return cell
}

You may set ImageViewFrameHeight greater than TableViewHeaderHeight and In your TableHeaderViewCell, set
TableHeaderViewCell.contentView.clipsToSubview = NO.
This'll definitely help you in getting your result.
Visual guide from XCode 7:

Please put this method and set your section's header height as you want.
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 100// return height which is greater than your image's height.
}

Related

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

UITableView Section Header Automatic Height Not Updated Properly

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

Unable to add consistent height and padding. between dynamic tableview cells

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 number​Of​Sections(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 table​View(_:​number​Of​Rows​In​Section:​)).
Let table​View(_:​number​Of​Rows​In​Section:​) 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:
table​View(:​view​For​Header​In​Section:​) and table​View(:​height​For​Header​In​Section:​).
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

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
}

after adding header cells don't appear

I have big image and after this I have table view. This two elements are on scroll view, and table view :
scrollEnabled = false
I had two cells in my tableView, and their height was counting by function in cell file(cause text in cells is dynamic)
func configure(#comment: Comment) {
userCommentTextView.text = comment.comment
userCommentTextView.accessibilityLabel = "Quote Content"
userCommentTextView.accessibilityValue = comment.comment
}
all was ok, I was counting scrollview size like
scrollView.contentSize.height = tableView.frame.origin.y + tableView.frame.height
in `func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {} delegate
BUT after I added custom header, all cells are not visible, there is only my header! Why? what is the problem? I checked, there is info for cells. And
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return comments.count
}
is NOT nil. But cellforrowindexpath isn't even executing. Can you help me?
Try adding your headerview by
func tableView(viewForHeaderInSection section: Int) -> UIView {}
and call
func tableView(heightForHeaderInSection section: Int) -> CGFloat {}
also
func numberOfSectionsInTableView() -> Int{}

Resources