I want to freeze a tableView cell on top of screen, so that while scrolling, other cells move but the top cell stays on its place.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath)
cell. //I think it must be here
return cell
Thank you.
Use these methods to create tableview header and add any subviews in it.
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = UIView.init()
header.backgroundColor = UIColor.gray
//Add subviews here
return header
}
try this:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 65
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = view as! UITableViewHeaderFooterView
header.textLabel?.textColor = UIColor.black
header.textLabel?.text="adadafaf"//ur data
}
Related
Interface:
Interface in debugger:
Here is configuration of tableview
private func configureTableView(){
view.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .none
// tableView.rowHeight = UITableView.automaticDimension
tableView.register(DishCell.self, forCellReuseIdentifier: "dishCell")
// tableView.sectionHeaderHeight = UITableView.automaticDimension
}
Here is tableView extensions
extension MenuViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 0 {
return 380
}
return 48
}
func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
return 122
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UITableView.automaticDimension
}
}
extension MenuViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return viewModel.dishes.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.dishes[section].count
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let dishType = viewModel.dishTypes[section]
if section == 0 {
let restaurant = viewModel.restaurant
return FirstMenuHeader(restaurant: restaurant, dishType: dishType)
}else{
return DefaultMenuHeader(dishType: dishType)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "dishCell") as! DishCell
let dish = viewModel.dishes[indexPath.section][indexPath.row]
cell.set(dish: dish)
return cell
}
}
Just to clarify DishCell, FirstMenuHeader and DefaultMenuHeader look well if you put them outside of UITableview. And they have constraints that define their height. However their height is dynamic and depends on amount of line of text.
Problem was in dishCell.I made constraints with view, while I had to make constraints with contentView.
I have rewrote my constraints and problem was resolved.
I using standard iOS UITableView loaded with data from a local database. I have implemented the delegates and datasource and registered my UITableView cell and header and everything looks fine. However after scrolling for couple of seconds, the tableview doesn't scroll again, this happens quickly if I scroll/swing very fast, the table view would just not responding to any touch event, no scroll, no cell selection. I don't know what am doing wrong. NB: There is no new data fetch so I don't reload the tableView data once initial data is loaded. This is my datasource class: TableCell is custom UITableViewCell while HeaderCell is custom UITableViewHeaderFooterView
func registerCells(tableView: UITableView) {
tableView.register(UINib.init(nibName: tableCell, bundle: nil), forCellReuseIdentifier: tableCell)
tableView.register(UINib(nibName: headerCell, bundle: nil), forHeaderFooterViewReuseIdentifier: headerCell)
print("\(sourceTag) register cells")
}
func numberOfSections(in tableView: UITableView) -> Int {
return viewModel.getNumberSections()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.viewModel.getNumberRowsInSection(section)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = viewModel.dataValues[indexPath.section]
let cell = tableView.dequeueReusableCell(withIdentifier: tableCell, for: indexPath) as! TableCell
cell.selectionStyle = .none
let quote = data.quotes[indexPath.row]
cell.setupWithQuote(quote, withSelectionDelegate: quoteSelectionDelegate)
return cell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let data = viewModel.dataValues[section]
let headerCell = tableView.dequeueReusableHeaderFooterView(withIdentifier: enquiryCell) as! HeaderCell
headerCell.setupData(data)
return headerCell
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return CGFloat.leastNormalMagnitude
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
return 161.0
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
//print("I'm scrolling!")
NSLog("I'm scrolling!")
}
#DonMag comment pointed me to the right direction. There was a delegate method which was vetted assigned multiple times which led to a cyclic issue and hence table views cell rendering issue
I am using below code for one fixed cell at the top and then list of items in below in a single tableview, I am able to load the data from firestore database, but the first item in from the database is not shown, it is kind of hidden behind the fixed "detailscell", rest the fixed cell and all other items from the database shows up, how to fix that?
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// print(posts)
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 && details1.count > 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "detailsCell") as! DetailsCellInHomeScreen
cell.set(details: details1[indexPath.row])
return cell
} else if posts.count > (indexPath.row - 1) {
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
cell.set(post: posts[indexPath.row - 1])
return cell
} else {
return UITableViewCell()
}
}
TableView has a function like below:
// MARK: - Headers and Footers
extension MyTableViewController {
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return MyCustomView()
}
}
You can use this function to return any view you want as a section header. Also note that sectionHeader views are sticky in default style tableView (not grouped style!). So you can use this as a advantage.
There are many tutorials like this one on the internet to follow and learn how to build a custom section section header for UITableView
You should add header on the table view:
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// print(posts)
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
cell.set(post: posts[indexPath.row - 1])
return cell
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 50))
let label = UILabel()
label.frame = CGRect.init(x: 5, y: 5, width: headerView.frame.width-10, height: headerView.frame.height-10)
label.text = "A Label on detailsCell"
headerView.addSubview(label)
return headerView
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
if the tableView has several section you can realize the section with section: Int object
tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? uses for create the header view and tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat uses for set header height
I am trying to customize static UITableViewController section header with UITableViewCell.
I could successfully cusomise section header in dynamic tableView by using the below set of code,
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell")
headerCell?.textLabel?.text = "Section \(section + 1)"
headerCell?.textLabel?.textColor = UIColor.blue
return headerCell
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
But, couldn't work for static tableview.
How to customise section header with static tableView
The problem is you should return a UIView, not a UITableViewCell in viewForHeaderInSection method.
Also you should keep an instance of header cell for future use (like modifying its view)
Create a field in your TableViewController like this:
private var headerViewCell: UITableViewCell?
and then in the viewForHeaderInSection do this:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell")
headerCell?.textLabel?.text = "Section \(section + 1)"
headerCell?.textLabel?.textColor = UIColor.blue
self.headerViewCell = headerCell
return headerCell?.contentView
}
I think you should unwrap cell when using dequeueReusableCell.
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell") as! HeaderCell // here header cell is your cell's custom class
headerCell.textLabel.text = "Section \(section + 1)"
headerCell.textLabel.textColor = UIColor.blue
return headerCell
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
I have a UITableView in a UIViewController nested in a UITabBarController that has multiple sections, each with a custom section header that is a subclass of a UIView. The UItableView has all the proper delegates and data sources set up in code and the storyboard.
The footer is explicitly set to 0 in code.
For whatever reason, it seems that the background (in red below) bleeds past each of the UITableViewCells in each section.
My UITableView currently looks like this:
My settings for the tableview in the storyboard looks like this:
and finally, here is the code that controls the tableView, written as extensions on the UITableView subclass:
extension TestViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 64
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 0
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 34
}
}
extension TestViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = TestHeaderView()
view.setLabelWithValues(valueType: "Example", amount: 1)
return view
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as! TestTableViewCell
cell.testLabel?.text = "example"
cell.testLabel2?.text = "example"
cell.testLabel3?.text = "example"
return cell
}
}
How do I prevent the background from going past each section of cells?
Figured it out:
Looks like I had to set the footer size to 0 (which then defaults to 1) in the storyboard size inspector column like so:
This will leave a single pixel width of footer, so switch the background color to whatever your cell is.