In a previous project using ObjectiveC, I had a multiple section tableView showing section headers with different background colours and with header text that dynamically updated itself dependent upon the number of items within the section. It worked perfectly.
I have tried to replicate this code in a new project in which we are using Swift and it doesn't work. The header text displays correctly, but there is no background colour and most importantly, the section header overlays the top cell in each section rather than sitting above it. This is the relevant code:
// MARK: TableView delegates
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if let sections = fetchedResultsController!.sections {
return sections.count
}
return 0
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let sections = fetchedResultsController!.sections {
let currentSection = sections[section]
return currentSection.numberOfObjects
}
return 0
}
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRectMake(0, 0, tableView.bounds.size.width, 30))
let textHeader = UILabel(frame: CGRectMake(11, 0, 320, 20))
switch (section) {
case 0:
headerView.backgroundColor = UIColor.greenColor()
case 1:
headerView.backgroundColor = UIColor.blueColor()
case 2:
headerView.backgroundColor = UIColor.redColor()
case 3:
headerView.backgroundColor = UIColor.purpleColor()
default:
break
}
let hText: String = "\(fetchedResultsController!.sections![section].name)"
let hItems: String = "\((fetchedResultsController!.sections![section].numberOfObjects) - 1)"
let headerText: String = "\(hText) - \(hItems)items"
textHeader.text = headerText
textHeader.textColor = UIColor.whiteColor()
textHeader.backgroundColor = UIColor.clearColor()
headerView.addSubview(textHeader)
return headerView
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat? {
return 20.0
}
The header overlays because its height is 30, and you return only 20.0 in heightForHeaderInSection func. the background color doesn't show up because you miss a break for each "case" in the switch statements.
Switch cases should end with break, then only it will return the backgroundcolor
Check below code
switch (section) {
case 0:
headerView.backgroundColor = UIColor.greenColor()
break
case 1:
headerView.backgroundColor = UIColor.blueColor()
break
case 2:
headerView.backgroundColor = UIColor.redColor()
break
case 3:
headerView.backgroundColor = UIColor.purpleColor()
break
default:
break
}
Related
Is there a way to add a photo in a section instead of adding the textviews?
for example bat-and-ball that only has one photo instead of all those textviews?
and in the other sections have the textviews?
?
I think you need something like this:
//
// ViewController.swift
// Test
//
// Created by Dennis Mostajo on 9/29/20.
//
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
// MARK: - UITableView
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
{
var height:CGFloat = 0
if tableView == self.table
{
height = 25
}
return height
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
var height:CGFloat = 0
if tableView == self.table
{
height = 50
}
return height
}
func numberOfSections(in tableView: UITableView) -> Int {
var sections:Int = 0
if tableView == self.table
{
sections = 4
}
return sections
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
var rows:Int = 0
if tableView == self.table
{
switch section
{
case 0:
rows = 3
break
case 1:
rows = 3
break
case 2:
rows = 2
break
case 3:
rows = 3
break
default:
break
}
}
return rows
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let headerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 25))
headerView.backgroundColor = .black
if tableView == self.table
{
switch section
{
case 0: // for image only
let imageView = UIImageView.init(frame: headerView.frame)
imageView.image = UIImage(named:"flagBolivia.png")
imageView.contentMode = .scaleToFill
headerView.addSubview(imageView)
break
case 1: // for image and text
let imageView = UIImageView.init(frame: headerView.frame)
imageView.image = UIImage(named:"flagBolivia2.jpg")
imageView.contentMode = .scaleToFill
headerView.addSubview(imageView)
let label = UILabel.init(frame: headerView.frame)
label.text = "Main Cities"
label.textColor = .white
label.font = UIFont.boldSystemFont(ofSize: 16.0)
label.backgroundColor = .clear
headerView.addSubview(label)
break
case 2: // for text only
let label = UILabel.init(frame: headerView.frame)
label.text = "Showing images only"
label.textColor = .white
label.backgroundColor = .black
headerView.addSubview(label)
break
case 3: // for text only
let label = UILabel.init(frame: headerView.frame)
label.text = "Bolivian Food"
label.textColor = .white
label.backgroundColor = .black
headerView.addSubview(label)
break
default:
break
}
}
return headerView
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell: UITableViewCell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell")
if tableView == self.table
{
switch indexPath.section
{
case 0:
switch indexPath.row
{
case 0:
cell.textLabel?.text = "CODING"
break
case 1:
cell.textLabel?.text = "FROM"
break
case 2:
cell.textLabel?.text = "BOLIVIA"
break
default:
break
}
break
case 1:
switch indexPath.row
{
case 0:
cell.textLabel?.text = "La Paz"
break
case 1:
cell.textLabel?.text = "Cochabamba"
break
case 2:
cell.textLabel?.text = "Santa Cruz"
break
default:
break
}
break
case 2:
switch indexPath.row
{
case 0: // for image only
let imageView = UIImageView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 50))
imageView.image = UIImage(named:"flagBolivia.png")
imageView.contentMode = .scaleToFill
cell.contentView.addSubview(imageView)
break
case 1:
let imageView = UIImageView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 50))
imageView.image = UIImage(named:"flagBolivia2.jpg")
imageView.contentMode = .scaleToFill
cell.contentView.addSubview(imageView)
let label = UILabel.init(frame: cell.frame)
label.text = "Custom Cell"
label.textColor = .white
label.font = UIFont.boldSystemFont(ofSize: 16.0)
label.backgroundColor = .clear
cell.contentView.addSubview(label)
break
default:
break
}
break
case 3:
switch indexPath.row
{
case 0:
cell.textLabel?.text = "Fricasé"
break
case 1:
cell.textLabel?.text = "Silpancho"
break
case 2:
cell.textLabel?.text = "MajadÃto"
break
default:
break
}
break
default:
break
}
}
return cell
}
}
Hi have an application where I use google autocomplete search but I had to write my networking code for it. The issue now is how do I show the Powered by Google text at the base of the tableView? I have check online for resources but havent got any option. Thanks in advance
You can add image in footer view :
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView?
{
if(section == tableView.numberOfSections - 1)
{
let footerView = UIView.init(frame: CGRect(x:0, y:0, width:tableView.frame.size.width, height:100))
footerView.backgroundColor = UIColor.clear
let imageView: UIImageView = UIImageView.init(frame: CGRect.init(x: 40, y: 0, width: footerView.frame.size.width - 80, height: 100))
imageView.image = #imageLiteral(resourceName: "google_logo")// google logo image
imageView.contentMode = UIViewContentMode.scaleAspectFit
footerView.addSubview(imageView)
return footerView
}
else
{
return nil
}
}
Please note you have to set footerView height as well :
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat
{
if(section == tableView.numberOfSections - 1)
{
return 100
}
else
{
return 0.001
}
}
I don't know why viewForHeaderInSection is not called in swift3. I've added heightForHeaderInSection in UITableView but not called unfortunately. Please help me to check how to fixed it.
func numberOfSectionsInTableView(_ tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch (section) {
case 0:
return homeStrs.count
case 1:
return accountStrs.count
case 2:
return otherStrs.count
default:
return otherStrs.count
}
}
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
let cell = menuTable.dequeueReusableCell(withIdentifier: "MenuCell", for: indexPath) as! MenuCell
cell.layoutMargins = UIEdgeInsets.zero;
cell.lbNoti.isHidden = true
switch ((indexPath as NSIndexPath).section) {
case 0:
cell.lbMenuTitle?.text = homeStrs[(indexPath as NSIndexPath).row]
cell.imgIcon.image = UIImage (named: homeImgStrs[(indexPath as NSIndexPath).row])
case 1:
cell.lbMenuTitle?.text = accountStrs[(indexPath as NSIndexPath).row]
cell.imgIcon.image = UIImage (named: accountImgStrs[(indexPath as NSIndexPath).row])
case 2:
cell.lbMenuTitle?.text = otherStrs[(indexPath as NSIndexPath).row]
cell.imgIcon.image = UIImage (named: otherImgStrs[(indexPath as NSIndexPath).row])
default:
cell.lbMenuTitle?.text = "Other"
}
return cell
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
switch (section) {
case 1:
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: self.menuTable.frame.size.width, height: 30))
let menuHeaderLabel = UILabel(frame: CGRect(x: 20, y: 0, width: self.menuTable.frame.size.width, height: 28))
menuHeaderLabel.text = "Account Settings"
headerView.addSubview(menuHeaderLabel)
return headerView
case 2:
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: self.menuTable.frame.size.width, height: 30))
let menuHeaderLabel = UILabel(frame: CGRect(x: 20, y: 0, width: self.menuTable.frame.size.width, height: 28))
menuHeaderLabel.text = "Others"
headerView.addSubview(menuHeaderLabel)
return headerView
default:
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: self.menuTable.frame.size.width, height: 0))
return headerView
}
}
If someone else is having the same issue... Adding this line in viewDidLoad called the delegate methods therefore made the header appear:
self.tableView.estimatedSectionHeaderHeight = 80
You sure you've added UITableViewDelegate, UITableViewDataSource in your ViewController Class
In my case, adding self.tableView.sectionHeaderHeight = 80.0 to viewDidLoad did the magic.
Same issue occured with me that's because tableview find difficulties in calculating height for header but as I was using automatic height calculation from xCode 9, I cannot give any explicit height value as mentioned above. After some experimentation I got solution, we have to override this method as,
-(CGFloat)tableView:(UITableView *)tableView
estimatedHeightForHeaderInSection:(NSInteger)section
{
return 44.0f;
}
Although I have checked both options
Automatic Height Calculation
Automatic Estimated Height Calculation
from storyboard as apple says, but still I got this weird error.
Please Note: This Error was shown only on IOS-10 version not on IOS-11 version. Maybe it's a bug from xCode. Thanks
It works perfectly on phones with a width of 320 like iPhone 4 and 5. When I test on the simulator for the 6 and up however, the uitableview section headers are no longer visible for some reason. Here is the relevant code:
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRectMake(0, 0, self.tableView.frame.size.width, 30))
headerView.backgroundColor = UIColor(red:0.20, green:0.47, blue:0.45, alpha:1.00)
let sectionLabel = UILabel(frame: CGRectMake(0, 0, self.tableView.frame.size.width, 30))
switch section {
case 0:
sectionLabel.text = "Monday to Friday"
case 1:
sectionLabel.text = "Saturday"
case 2:
sectionLabel.text = "Sunday"
default:
sectionLabel.text = ""
}
sectionLabel.font = UIFont(name:"HelveticaNeue-Bold", size: 16.0)
sectionLabel.textColor = UIColor.whiteColor()
sectionLabel.textAlignment = NSTextAlignment.Center;
headerView.addSubview(sectionLabel)
return headerView
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> Float {
return 30.0
}
BEFORE I tap on first tableview cell...
WHILE I tap on first tableview cell...
This is it working on iPhone 5...
I'm trying to make section headers with autolayout.
A simple header with a title and a counter
class ProfilePeopleListHeaderViewCell: UIView {
let titleLeftOffset = 12
let counterRightOffset = 5
let counterWidth = 50
var title = "title" {
didSet {
titleLabel.text = title
}
}
var numberOfPeople = 0 {
didSet {
peopleCounter.text = "\(numberOfPeople)"
}
}
let titleLabel = UILabel()
let peopleCounter = UILabel()
convenience init(title: String, numberOfPeople:Int) {
self.init()
self.title = title
self.numberOfPeople = numberOfPeople
backgroundColor = UIColor.greenColor()
titleLabel.textColor = Constants.Colors.ThemeGreen
titleLabel.textAlignment = .Left
if #available(iOS 8.2, *) {
titleLabel.font = Constants.Fonts.Profile.PeopleListHeaderFont
peopleCounter.font = Constants.Fonts.Profile.PeopleListHeaderFont
} else {
titleLabel.font = UIFont.systemFontOfSize(14)
peopleCounter.font = UIFont.systemFontOfSize(14)
}
peopleCounter.textAlignment = .Right
peopleCounter.textColor = Constants.Colors.ThemeDarkGray
addSubview(titleLabel)
addSubview(peopleCounter)
self.titleLabel.snp_makeConstraints { (make) -> Void in
make.centerY.equalTo(self)
make.height.equalTo(self)
make.width.equalTo(peopleCounter).multipliedBy(3)
make.left.equalTo(self).offset(titleLeftOffset)
}
self.peopleCounter.snp_makeConstraints { (make) -> Void in
make.centerY.equalTo(self)
make.height.equalTo(self)
make.width.equalTo(counterWidth)
make.left.equalTo(titleLabel.snp_right)
make.right.equalTo(self).offset(counterRightOffset)
}
}
}
The code to retrieve the header is:
let mutualFriendsSectionView = ProfilePeopleListHeaderViewCell(title: Strings.Title.MutualFriends, numberOfPeople: 0)
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if section == 1 {
//mutualFriendsSectionView.layoutSubviews()
return mutualFriendsSectionView
}
}
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
I get a green background in the section header.
But I don't see any label...
Try this out for UITableView Section Header.
Programatically create headerview
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView.init(frame: CGRectMake(0, 0, tblView.bounds.size.width, 50))
let lblHeader = UILabel.init(frame: CGRectMake(15, 13, tableView.bounds.size.width - 10, 24))
if section == 0 {
lblHeader.text = "Image Settings"
}
else if section == 1 {
lblHeader.text = "Personal Settings"
}
else {
lblHeader.text = "Other Settings"
}
lblHeader.font = UIFont (name: "OpenSans-Semibold", size: 18)
lblHeader.textColor = UIColor.blackColor()
headerView.addSubview(lblHeader)
headerView.backgroundColor = UIColor(colorLiteralRed: 240.0/255.0, green: 240.0/255.0, blue: 240.0/255.0, alpha: 1.0)
return headerView
}
Height for HeaderView
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
Check if a tableView delegate is connected
Actually it's working.
my mistake was to believe that didSet{} was also called within the class -> it's not the case.
When I was setting the title in the init() it was not setting the label text.
try instantiating your headerView inside viewForHeader method
Edit your code as below
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let mutualFriendsSectionView = ProfilePeopleListHeaderViewCell(title: Strings.Title.MutualFriends, numberOfPeople: 0)
if section == 1
{
//mutualFriendsSectionView.layoutSubviews()
return mutualFriendsSectionView
}
}