Two headers in ViewForHeaderInSection - ios

I want two headers at the top of the view controller that does not disappear as the table is scrolled.
The first section of code displays a top header that I have in viewDidLoad. The viewForHeaderInSection works correctly. How do I add the header to the viewForHeaderInSection?
let header = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 100))
header.backgroundColor = UIColor.red
//header.addSubview(header)
tableView.tableHeaderView = header
/////////
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let v = UIView()
v.backgroundColor = UIColor.white
let segmentControl = UISegmentedControl(frame: CGRect(x: 10, y: 5, width: tableView.frame.width, height: 30))
segmentControl.insertSegment(withTitle: "one", at: 0, animated: false)
segmentControl.insertSegment(withTitle: "two", at: 1, animated: false)
segmentControl.insertSegment(withTitle: "three", at: 2, animated: false)
v.addSubview(segmentControl)
return v
}

Just add one view (segmentControl) as a subview of another view (v). And then return that as your view for the viewForHeaderInSection. You have to use constraints between segmentControl & v instances.
And don't forget, for the segmentControl you must set translatesAutoresizingMaskIntoConstraints to false. However you should NOT set translatesAutoresizingMaskIntoConstraints to false for the v instance, because you don't manage the outer constraints for that, the tableview will do it for you...

I think this helpful to you:
//Your Tableview
#IBOutlet var tblviewSideMenu: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
let screenSize: CGRect = tblviewSideMenu.frame
let myView = UIView(frame: CGRect(x: 0, y: 0, width: screenSize.width,height: 145))
myView.backgroundColor = UIColor(red: 0.0/255.0, green: 88.0/255.0, blue: 181.0/255.0, alpha: 1.0)
tblviewSideMenu.addSubview(myView)
tblviewSideMenu.tableHeaderView = myView
tblviewSideMenu .reloadData()
tblviewSideMenu.tableFooterView = UIView()
}
Note: if you want two headers add one more view

Related

Swift 5 - UIButtons Side by side in tableView footer with original separator line

I am trying to add two buttons programmatically side by side (on the bottom left) in the tableView footer.
The issue that I am having is that I have to manually draw the separator line when defining the tableView footer because the separator line disappears.
How can I simply add two buttons to the bottom left of the tableView footer without loosing the original separator line?
var terms_button = UIButton()
var policy_button = UIButton()
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
//terms button
terms_button = UIButton(frame: CGRect(x: 70, y: 0, width: 100, height: 50))
terms_button.setTitle("Terms", for: .normal)
terms_button.setTitleColor(UIColor.black, for: .normal)
terms_button.titleLabel?.font = UIFont.roboto(size: 12, weight: .medium)
terms_button.titleLabel?.alpha = 0.38
terms_button.addTarget(self,action: #selector(didTapTermsButton),for: .touchUpInside)
//policy button
policy_button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
policy_button.setTitle("Privacy Policy", for: .normal)
policy_button.setTitleColor(UIColor.black, for: .normal)
policy_button.titleLabel?.font = UIFont.roboto(size: 12, weight: .medium)
policy_button.titleLabel?.alpha = 0.38
policy_button.addTarget(self,action: #selector(didTapPolicyButton),for: .touchUpInside)
let result = UIView()
// recreate insets from existing ones in the table view
let insets = tableView.separatorInset
let width = tableView.bounds.width - insets.left - insets.right
let sepFrame = CGRect(x: insets.left, y: -0.5, width: width, height: 0.5)
// create layer with separator, setting color
let sep = CALayer()
sep.frame = sepFrame
sep.backgroundColor = tableView.separatorColor?.cgColor
result.layer.addSublayer(sep)
result.addSubview(policy_button)
result.addSubview(terms_button)
return result
}
When you are returning your own let result = UIView() view instance from viewForFooterInSection, you are discarding the original built-in default view provided by the iOS.
What you can attempt is -
delete the viewForFooterInSection implementation
try to use default built-in view provided by iOS
try to customize default view's appearance like following
func tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int) {
guard let footerView = view as? UITableViewHeaderFooterView else { return }
let contentView = footerView.contentView
// Try adding your buttons to this `contentView`
}
This is the only way to try to keep using built-in view with possible customizations. If this doesn't work reliably across different iOS versions, you would need to go back to viewForFooterInSection custom view implementation.

How to increase the width of custom cells in UITableView

I have created the UITableView with the custom UITableViewCell. But the problem which I am getting is the width of the cells is not the frame width though I have assigned in the CGReact. Please have a look over my code :
CustomTableViewCell Class:
import UIKit
class CustomTableViewCell: UITableViewCell {
lazy var backView : UIView = {
let view = UIView(frame: CGRect(x: 10, y: 6, width: self.frame.width, height: 76))
view.backgroundColor = .red
view.layer.applySketchShadow()
return view
}()
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
lazy var iconTime : UIImageView = {
var object = UIImageView(frame: CGRect(x: 10, y: 54, width: 12, height: 12))
object.image = #imageLiteral(resourceName: "clock")
return object
}()
lazy var notification : UILabel = {
var object = UILabel(frame: CGRect(x: 10, y: 7, width: backView.frame.width, height: 40))
object.adjustsFontSizeToFitWidth = true
object.minimumScaleFactor = 0.5
object.font = object.font.withSize(28.0)
object.numberOfLines = 3
return object
}()
lazy var notificationTime : UILabel = {
var object = UILabel(frame: CGRect(x: 30, y: 40, width: backView.frame.width, height: 40))
object.adjustsFontSizeToFitWidth = true
object.minimumScaleFactor = 0.5
object.font = object.font.withSize(12.0)
return object
}()
override func layoutSubviews() {
contentView.backgroundColor = UIColor.clear
backgroundColor = UIColor.clear
backView.layer.cornerRadius = 5
backView.clipsToBounds = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
addSubview(backView)
[notification, notificationTime, iconTime].forEach(backView.addSubview(_:))
}
}
And my view controller as follows :
import UIKit
class UserModal {
var tableView = UITableView()
var notification: String?
var notificationTime : String?
init(notification: String, notificationTime: String) {
self.notification = notification
self.notificationTime = notificationTime
}
}
class newNotificationController : UIViewController {
var tableView = UITableView()
var userMod = [UserModal]()
override func viewDidLoad() {
super.viewDidLoad()
setTableView()
userMod.append(UserModal(notification: "Data ", notificationTime: "Time"))
userMod.append(UserModal(notification: "This is some Notification which needs to be populated in the Grid view for testing but lets see what is happening here!! ", notificationTime: "12-12-1212 12:12:12"))
userMod.append(UserModal(notification: "Data ", notificationTime: "Time"))
}
func setTableView() {
tableView.frame = self.view.frame
tableView.backgroundColor = UIColor.clear
tableView.delegate = self
tableView.dataSource = self
tableView.separatorColor = UIColor.clear
self.view.addSubview(tableView)
tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "cell")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.setNavigationBarHidden(false, animated: animated)
}
}
extension newNotificationController: UITableViewDelegate , UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userMod.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? CustomTableViewCell else { fatalError("Unable to populate Notification History")}
cell.notification.text = userMod[indexPath.row].notification
cell.notificationTime.text = userMod[indexPath.row].notificationTime
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 85
}
}
Please have a look over the result:
I am not getting it why the width of my cells is the width of the frame. Any help will be highly appreciated. Thanks!!
The problem is in this code is frame width, somehow the width of the self is not the width of a device, so because of this, you are facing this issue.
lazy var backView : UIView = {
let view = UIView(frame: CGRect(x: 10, y: 6, width: self.frame.width, height: 76))
view.backgroundColor = .red
view.layer.applySketchShadow()
return view
}()
To resolve this issue you can set frame like this
let view = UIView(frame: CGRect(x: 10, y: 6, width: UIScreen.main.bounds.size.width - 10, height: 76))
You set the width your view
UIView(frame: CGRect(x: 5, y: 6, width: self.frame.width - 10,
height: 76))
tableView.frame = CGRect(x: 0, y: 0, width:
self.view.frame.size.width, height: self.view.frame.size.height)
you need to give constraint to the tableview. Top, Leading, Trailing, Bottom.
put this tableView.translatesAutoresizingMaskIntoConstraints = false line in your function
func setTableView() {
tableView.frame = self.view.frame
tableView.backgroundColor = UIColor.clear
tableView.delegate = self
tableView.dataSource = self
tableView.separatorColor = UIColor.clear
self.view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false //add this line
tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "cell")
}
and change width: UIScreen.main.bounds.size.width - 10 it.
thanks..

Swift 4 Move Location of UIButton

I've been searching all around the other questions but none of the solutions I've read worked for me.
I have this code I need to modify so that when the button's title changes, it still appears to be aligned with some other items in the table. The button was declared programmatically as shown below:
internal func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if section % 2 != 0 {
let frame : CGRect = tableView.frame
btnSelectAll = UIButton(frame: CGRect(x: frame.size.width-92, y: 0 , width: 100, height: 30))
btnSelectAll.setTitle(btnTitle, for: .normal)
btnSelectAll.setTitleColor(UIColor.blue, for: .normal)
let lblTitle : UILabel = UILabel(frame: CGRect(x: 19, y: 0, width: 120, height: 30))
btnSelectAll.addTarget(self, action:#selector(selectAllClicked(sender:)), for: .touchUpInside)
lblTitle.text = Constants.FILTER_DEPARTMENT_SECTION
lblTitle.font = UIFont.boldSystemFont(ofSize: 17)
let headerView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
headerView.backgroundColor = UIColor.white
headerView.addSubview(btnSelectAll)
headerView.addSubview(lblTitle)
return headerView
}
return nil
}
I tried to change it like so here:
if filter[Constants.FILTER_DEPARTMENT_SECTION]?.count == department.count {
if let btnSelectAll = btnSelectAll {
let frame : CGRect = tableView.frame
let newFrame = CGRect(x: frame.size.width-150, y: 0 , width: 100, height: 30)
btnSelectAll.frame = newFrame
btnSelectAll.setTitle(Constants.DESELECT_ALL, for: .normal)
btnSelectAll.setNeedsDisplay()
}
}
Unfortunately I still can't get it to move.
Use btnSelectAll.sizeToFit(),
As Apple says:
Call this method when you want to resize the current view so that it uses the most appropriate amount of space. Specific UIKit views resize themselves according to their own internal needs. In some cases, if a view does not have a superview, it may size itself to the screen bounds. Thus, if you want a given view to size itself to its parent view, you should add it to the parent view before calling this method.

Programmatically adding constraints to a UITableView header

I have a header on my tableview, which has an image and a label. I want to center the UIImage and have the label pinned underneath it. This is my code currently:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerLabel = UILabel()
let logoView = UIImageView()
headerLabel.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 21)
headerLabel.text = self.navigationItem.title
headerLabel.textColor = UIColor.white
headerLabel.backgroundColor = UIColor.clear
headerLabel.textAlignment = NSTextAlignment.center
logoView.frame = CGRect(x: 0, y: 0, width: 90, height: 90)
let logo: UIImage = UIImage(named: self.navigationItem.title!)!
logoView.image = logo
logoView.contentMode = .scaleAspectFill
view.addSubview(headerLabel)
view.addSubview(logoView)
return topView
}
This puts the label centered on the top of the header, and the logo in the top left corner. How can I add constraints (programmatically, no storyboard) to center the image and pink the label below it? I've been using programmatic constraints quite a bit (i.e. something.leftAnchor.constraint(equalTo....) but I'm not sure how to apply it in this situation as it's my first use of a header.
I want to center the UIImage and have the label pinned underneath it.
This can be achieved by making the framing logic of each subview dependent of the neighbouring views. Whilst doing this programmatically, one has to be extra careful about the geometric calculations involved.
This snippet should do it:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let logoView = UIImageView()
logoView.frame = CGRect(x: tableView.center.x - 90/2, y: 0, width: 90, height: 90)
let logo: UIImage = UIImage(named: self.navigationItem.title!)!
logoView.image = logo
logoView.contentMode = .scaleAspectFill
view.addSubview(logoView)
let headerLabel = UILabel()
headerLabel.frame = CGRect(x: 0, y: logoView.frame.size.height, width: view.frame.width, height: 21)
headerLabel.text = self.navigationItem.title
headerLabel.textColor = UIColor.white
headerLabel.backgroundColor = UIColor.clear
headerLabel.textAlignment = NSTextAlignment.center
view.addSubview(headerLabel)
return topView
}
You can use that code to set default paddings.
if #available(iOS 15.0, *) { tableView.sectionHeaderTopPadding = 0 }

Swift Add Footer View In UITableView

This is actually a tableview and tableview cell, and i wanted to add a Submit button after the end of the tableview cell, but how do i do it?
I tried to do it at the storyboard add the button manually, but its not working, the button is not showing. Is there any other way to do it?
I wanted to do like the screenshot below.
Using StoryBoard
In UITableView You can drag UIView, it will set as FooterView if you have more then 0 prototype cell. After Drag you can see it in table view hierarchy as a subview. Now, you can add the label button on that View, you can also set IBAction into ViewController Class File.
Programmatically
Follow 3 Steps
Make one custom view with button,
Swift 3.X / Swift 4.X
let customView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
customView.backgroundColor = UIColor.red
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
button.setTitle("Submit", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
customView.addSubview(button)
Swift 2.X
let customView = UIView(frame: CGRectMake(0, 0, 200, 50))
customView.backgroundColor = UIColor.redColor()
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
button.setTitle("Submit", forState: .Normal)
button.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
customView.addSubview(button)
Add that view in Table Footer View.
Swift 2.X/Swift 3.X/Swift 4.X
myTblView.tableFooterView = customView
you can do action on that button in same class.
Swift 3.X/Swift 4.X
#objc func buttonAction(_ sender: UIButton!) {
print("Button tapped")
}
Swift 2.X
func buttonAction(sender: UIButton!) {
print("Button tapped")
}
Swift 3/4
1. If you want to add Table footer which is only visible at the end of TabelView
let customView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 150))
customView.backgroundColor = UIColor.clear
let titleLabel = UILabel(frame: CGRect(x:10,y: 5 ,width:customView.frame.width,height:150))
titleLabel.numberOfLines = 0;
titleLabel.lineBreakMode = .byWordWrapping
titleLabel.backgroundColor = UIColor.clear
titleLabel.textColor = PTConstants.colors.darkGray
titleLabel.font = UIFont(name: "Montserrat-Regular", size: 12)
titleLabel.text = "Payment will be charged to your Apple ID account at the confirmation of purchase. Subscription automatically renews unless it is canceled at least 24 hours before the end of the current period. Your account will be charged for renewal within 24 hours prior to the end of the current period. You can manage and cancel your subscriptions by going to your account settings on the App Store after purchase."
customView.addSubview(titleLabel)
tableView.tableFooterView = customView
2. If you want to add section footer which is visible while scrolling through section.
Adopt UITableViewDelegate and implement following delegate method.
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let vw = UIView()
vw.backgroundColor = UIColor.clear
let titleLabel = UILabel(frame: CGRect(x:10,y: 5 ,width:350,height:150))
titleLabel.numberOfLines = 0;
titleLabel.lineBreakMode = .byWordWrapping
titleLabel.backgroundColor = UIColor.clear
titleLabel.font = UIFont(name: "Montserrat-Regular", size: 12)
titleLabel.text = "Footer text here"
vw.addSubview(titleLabel)
return vw
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 150
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 50))
return footerView
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 50
}
Add UILabel as UITableView.Footer in swift
let footerView:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width:320 , height: 500))
footerView.text = "add description ro Timevc in order user will see the result of lesson time"
footerView.numberOfLines = 0;
footerView.sizeToFit()
tableView.tableFooterView = footerView
tableView.contentInset = (UIEdgeInsetsMake(0, 8, -footerView.frame.size.height, 8))
// for Header and footer
// for header
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let HeaderView = UIView(frame: CGRect(x: 0, y: 0, width: TableViews.frame.size.width, height: 10))
HeaderView.backgroundColor = .green
let HeaderTitle = UILabel(frame: CGRect(x: 10, y: 10, width: TableViews.frame.size.width, height: 20))
HeaderTitle.text = "Hi You Welcome"
HeaderView.addSubview(HeaderTitle)
return HeaderView
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 40 }
// for footer
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footer = UIView()
footer.backgroundColor = UIColor.green
let titleLabel = UILabel(frame: CGRect(x: 10, y: 5, width: 350, height: 30))
titleLabel.textColor = .blue
titleLabel.text = "Hi I am Muhammad Hassan"
footer.addSubview(titleLabel)
return footer
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { 40 }
... this is the best function for the header and footer ...
You can use
tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 16, right: 0)

Resources