Add UIView Above All Section in UITableView Swift - ios

i am not talking about a section i want put a uiview on the above of every section
This is the layout
here Menu and LeftOver are uiView
Staters and new are sections

What you're looking for is a section header. You can easily configure your own custom view by implementing the UITableViewDataSource method
For example:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
// configure view, note the method gives you the section to help this process
return headerView
}
you may also want to implement this function
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50 // or whatever it is
}
Do keep in mind that header are sticky be default
in the past I've gotten around this fairly easily doing something like this:
let dummyViewHeight = CGFloat(49) // height of header (set in storyboard)
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)
which basically just makes the table header "stick" to this inset on top of the table. (unless you really do want it hovering over the section at the top)
Edit:
Given the OP considers this "not satisfying" I'm like 99% confident when I say the ONLY other reasonable option (if you don't wan't to use section header or footer views) is to then make a new UITableViewCell subclass. Then that new subclass would appears at the top of each section.
So in the cellForIndexPath: method you'd check if indexPath.row == 0and if so dequeue a cell with a different identifier. That way the header just becomes a cell that is built differently.
If you're doing it programmatically just be sure to register that cell (tableView.register(MyNewHeaderCellSubclass.self, forCellReuseIdentifier: "MyNewHeaderCellSubclass")) or otherwise go to the table view on the storyboard and toggle the option for two types of dynamic cell classes.
The section header is exactly what this use case is for however. I cant think of any other solution without just abandoning UITableView completely which I think would be a big mistake. Good luck to you otherwise if so.

Related

Why are separator insets not being respected for the first and last cell in a grouped section?

I want to be able to have all of my separators in a table view to be inset by a certain amount. This table view needs a custom header for each section. See the following image for the desired insets:
My storyboard is set up so that I have a UIViewController which contains a container UIView, which in turn has an embed segue for a UITableView. My table view specifies a prototype cell, and I have set in the storyboard a Grouped style, Default separator, with Automatic inset.
On my Table View Cell in the storyboard, I have a Custom separator inset of 26 on the left.
In my table view controller, I have implemented the following two methods:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "ItemHeader") as! TableSectionHeaderViewCell
header.title.text = "My Custom Date Header"
return header
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 60.0
}
In a separate file I have subclassed UITableViewHeaderFooterView to just set a font, text color, and some constraints.
Now if I set a custom separator inset on the storyboard at the table view level with 26 inset from the left, either From Cell Edges or From Automatic Insets, nothing changes with the separators that appear below each of my headers. Similarly, if I set these values programmatically in the viewDidLoad method of my table view controller, like so:
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableView.automaticDimension
tableView.register(TableSectionHeaderViewCell.self, forHeaderFooterViewReuseIdentifier: "ItemHeader")
tableView.separatorInset = UIEdgeInsets(top: 0, left: 26, bottom: 0, right: 0)
tableView.separatorStyle = .singleLine
tableView.separatorInsetReference = .fromCellEdges
}
Nothing changes with the separator insets, even using the .fromAutomaticInsets option for the separator inset reference. Here is what I am actually seeing:
It seems that the first and last cells in a section are actually not respecting the separator insets. I thought originally that this was an issue related to having a header for each grouped section, but the separator on the final cell with no header below it seems to indicate otherwise. How can I make it so that these separators all are inset by 26pts? Thank you for any insight you can provide.
Check this thread then, I think it will help:
Grouped UITableview remove outer separator line
I can see that they removed the default separator (Using Clear Color) and put a custom view for the separator themselves.
The other option I can suggest is don’t use a group style Table view, use the plain one and handle it yourself.

How to scroll beyond the last cell in a UITableView or UICollectionView

I want a tableView (and collectionView) to scroll beyond the last cell.
That is, when scrolling, and you reach the last cell, I want the tableView to continue scrolling for lets say 200 points more past the last cell.
I tried:
tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 200, right: 0)
But the behaviour of this code just like changing the frame (The whole tableView move up 200 points). Which is not what I want.
In a table view you can add a view of the desired height as the table view's footer.
let footer = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 200))
self.tableView.tableFooterView = footer
Depending on the look, you may want to set the background color of the footer view.
For a collection view you can setup a section footer for the last section of the collection view.
Collection View
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
// Section Insets
}
There is no straight forward way to do this with a UITableView, but you can create a footer view with tableView(_ tableView: UITableView, viewForFooterInSection section: Int) and use the tableView(_ tableView: UITableView, heightForFooterInSection section: Int) to add extra height to the last section giving that scrolling effect.
Simple approach using Size inspector.
Select collection View in xib or storyboard, go to size inspector.
Set value in Footer Size to 30 40 or as per your need.
Run it.
Scroll now works beyond actual height of collection view.

hiding tableView.tableFooterView causes my section headerView to disappear

I have a tableViewController with one section. I have added a UIView directly to the tableView in storyboard and set outlets to my tableViewController for that view (headerView) and it's contents which are a segmented control and a searchBar.
In the tableView delegate methods I have the following for my header:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return headerView
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 88
}
Everything is working fine except that there is no separator for the very last row of my tableView. This is expected and the workaround for me has always been the following in viewDidLoad:
self.tableView.tableFooterView = UIView(frame: CGRect.zero)
self.tableView.tableFooterView?.isHidden = true
For some reason, these two lines of code cause my headerView to completely disappear from the table.
I could create a tableViewCell and use that as my tableView header but there is a lot of delegation required for the searchBar and segmented control and that leads to other problems. Mainly that the searchBar wants to resignFirstResponder every time I reload my tableView. Again there are workarounds for that but it all starts to get a bit messy.
Just wondering why my headerView is disappearing and what I could do about it.
Remove that header view from tableview and add it on UIViewController i.e directly drag them adjacent to first responder and exit. Then using IBOutlet you can use it as Section view. Here it is being treated as footer view as well.
It is because you assign the new UIView object to table header view
If you want to toggle table header then you have to follow below step
1) keep the reference of you view which you want to set in table header
UIView footerView = your storyboard referance
2) when you want to hide then just assign nil to table footer
self.tableView.tableFooterView = nil
3) Now when you want to show then again assign your refence view
self.tableView.tableFooterView = footerView

Resizing UIStackView after changing UILabel number of lines

My iOS app has a tableview with one UITableViewCell with the following layout (1 stackview containing 2 labels and 1 button)
When the user taps the button the number of lines of the central label goes from 0 to 2 and will look like this:
Now there are two problems here:
1) Resizing the UIStackView
2) Resizing the cell
I have found a not-optimal solution for problem 1, which consists of adding an empty view in the stack. (invalidateIntrinsicContentSize was not working).
let emptyView = UIView()
emptyView.frame = CGRect(x: 0, y: 0, width: 0, height: 0)
stackView.addArrangedSubview(emptyView)
As you can see in the second screenshot the cell doesn't resize and I'm not sure if this is due to the stackview or the cell itself.
I would like to point the fact that I'm writing code inside the UITableViewCell subclass as the button event is handled inside it.
For the records The Tableview is using dynamic sizing:
// dynamic cell sizing
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return CGFloat(cellEstimatedHeight)
}
UIStackView may or may not be your best bet... it's designed more for arranging views inside its own frame, rather than adjusting its own frame to the views.
For a layout as simple as you have there, it would probably be much better to just lay out the elements with normal constraints.
Take a look at this example: https://github.com/DonMag/DynamicCellHeight
Table B is one way of accomplishing your layout (Table A was for another layout I played around with).
I had to do a little trickery to get the main label to stay in place while the cell resized... could probably find a better way. (Re-Edit - yep, found a better way)
Let me know if it makes sense - no doubt you'll want to do some tweaking.

iOS UITableView Custom Footer with UIView

I want to make a custom footer for my UITableView.
For that, I will need the position of the last cell in the UITableView and set my UIView under the TableView.
But I don't know how to get the position of the last cell.
Is it even possible to make this kind of custom Tableview-footer?
You can add a footer directly in the storyboard or xib--just drag your view so that it's inside your tableView, but after all of the tableView's cells.
You don't need to make custom footer or to know the position of your last cell. It is already available on UITableViewDelegate.
You need to make a custom UIView then on the callback of func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? return the UIView.
Example:
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let view = UIView.init(frame: CGRectMake(0, 0, tableView.frame.size.width, tableView.frame.size.height))
view.backgroundColor = UIColor.greenColor()
return view
}
The above code will give you a green UIView for the UITableView. Just make sure you do not set the Footer height to 0 on Storyboard or on code.

Resources