Altering table cell header on action in swift - ios

I have a header in my sectioned table view that contains a button that expands its cells when tapped, I have a right ward facing arrow in the header as well, and when the header is tapped I want to change that arrow image to a downward facing arrow, how can I alter the section's header? Specifically the arrowButton
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 50))
let button = UIButton(frame: CGRect(x: 0, y: 0, width: tableView.frame.width - 30, height: 50))
button.setTitle(tableDataSource[section][0].mod.modType!, for: .normal)
button.titleLabel?.font = UIFont(name: "Helvetica neue", size: 20)
button.addTarget(self, action: #selector(headerPressed(sender:)), for: .touchUpInside)
button.titleLabel?.textAlignment = .left
button.tag = section
let arrowButton = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
arrowButton.setImage(UIImage(systemName: "chevron.right", compatibleWith: nil), for: .normal)
header.addSubview(arrowButton)
header.addSubview(button)
header.backgroundColor = UIColor.green
return header
}
#objc func headerPressed(sender: UIButton){
if(tableDataSource[sender.tag][0].clicked == false){
tableDataSource[sender.tag][0].clicked = true
} else {
tableDataSource[sender.tag][0].clicked = false
}
let sections = IndexSet.init(integer: sender.tag)
tableView.reloadSections(sections, with: .fade)
}

You need to change this inside viewForHeaderInSection
let name = tableDataSource[section][0].clicked ? "chevron.right" : "chevron.left"
arrowButton.setImage(UIImage(systemName:name, compatibleWith: nil), for: .normal)
And calling this tableView.reloadSections(sections, with: .fade) will do the reload job

Related

Swift sender.setTitle code didn't visible?

I have question about sender title. I have a button and I want to change title according to some condition. In this point I made sender.setTitle() code but title appear only like 0.5 second. Its not visible let me say more clear. How can I solve it?
Here my code:
#objc func handleExpandCloseForAlim(sender: UIButton) {
if (sender.tag == 1) {
if keys[0] == 0 {
sender.setTitle("titlesample", for: .normal)
keys[0] = 1
}else{
keys[0] = 0
sender.setTitle("titlesampleclose", for: .normal)
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
Here my header view code:
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 100))
// code for adding centered title
headerView.backgroundColor = .lightGray
let headerLabel = UILabel(frame: CGRect(x: 0, y: 10, width: tableView.bounds.size.width, height: 28))
headerLabel.textColor = UIColor.black
headerLabel.text = " Teslim Alınacağı Adres"
headerLabel.font = UIFont.boldSystemFont(ofSize: 14)
headerLabel.textAlignment = .left
headerView.addSubview(headerLabel)
// code for adding button to right corner of section header
let button: UIButton = UIButton(frame: CGRect(x:headerView.frame.size.width - 100, y:8, width:100, height:28))
button.setTitleColor(.black, for: .normal)
button.titleLabel!.font = UIFont.boldSystemFont(ofSize: 14)
button.layer.cornerRadius = 4
button.tag = 1
button.backgroundColor = UIColor.blue
button.addTarget(self, action: #selector(handleExpandCloseForAlim(sender:)), for: .touchUpInside)
headerView.addSubview(button)
return headerView
The problematic part in the code above is that you are reloading your tableview in the handleExpandCloseForAlim. Since your tableView is reloaded, it will invoke viewForHeaderInSection function in your tableView from where you are returning a headerView with no title. That's why your label is getting disappeared.
You can solve this by having your button label as a field in your viewcontroller may be. Sample code may be like the one follows.
class YourViewController: UITableViewController {
var buttonLabel: String = "titlesampleclose"
.......
}
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 100))
// code for adding centered title
headerView.backgroundColor = .lightGray
.........
.........
button.setTitle(buttonLabel,for: .normal)
button.addTarget(self, action: #selector(handleExpandCloseForAlim(sender:)), for: .touchUpInside)
headerView.addSubview(button)
return headerView
#objc func handleExpandCloseForAlim(sender: UIButton) {
if (sender.tag == 1) {
if keys[0] == 0 {
self.buttonLabel = "titlesample"
keys[0] = 1
}else{
keys[0] = 0
self.buttonLabel = "titlesampleclose"
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
Hope it helps.

How to add two UIButtons in Tableview section header

I added custom tableview header with two buttons, but buttons are disabled , unable to make control events. i want to get layout like this. i'm new to development. any suggestions or solution
i tried to add view with buttons inside view in ViewforHeaderSection function
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let inviteSectionHeaderview = UIView.init(frame: CGRect(x:0, y:0, width: self.view.bounds.width, height: self.view.bounds.height))
let selectAllBtn = UIButton.init(frame:CGRect(x:16, y: inviteSectionHeaderview.bounds.height/2, width:130, height:20))
let sendButton = UIButton.init(frame:CGRect(x:inviteSectionHeaderview.bounds.width - 30, y: inviteSectionHeaderview.bounds.height/2, width:60, height:20))
selectAllBtn.setTitle("select all/Cancel", for: .normal)
selectAllBtn.backgroundColor = .black
sendButton.backgroundColor = .black
sendButton.setTitle("SEND", for: .normal)
self.contactsTable.addSubview(inviteSectionHeaderview)
inviteSectionHeaderview.addSubview(selectAllBtn)
inviteSectionHeaderview.addSubview(sendButton)
return inviteSectionHeaderview
}
You have two options:
Create your UIView in storyboard
Create programatically
Option 2
Create your UIView.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 30.0))
// Button1
let button1 = UIButton(frame: CGRect(x: 15.0, y: 0, width: 100, height: 28.0)
button1.setTitle("Button 1", for: .normal)
button1.addTarget(self, action: #selector(selectorButton1), for: .touchUpInside)
// Button2
let button2 = UIButton(frame: CGRect(x: tableView.frame.width-150, y: 0, width: 150, height: 30.0))
button2.setTitle("Button2", for: .normal)
button2.addTarget(self, action: #selector(selectorButton2), for: .touchUpInside)
button2.semanticContentAttribute = UIApplication.shared
.userInterfaceLayoutDirection == .rightToLeft ? .forceLeftToRight : .forceRightToLeft
headerView.addSubview(button1)
headerView.addSubview(button2)
return headerView
}
#objc func selectorButton1(_ sender : Any) {
}
#objc func selectorButton2(_ sender : Any) {
}
In this case, you must set correctely y and x positions when create UIView(frame: CGRect()) and UIButton(frame: CGRect())
EDIT
From your code, you just need add the targets:
selectAllBtn.addTarget(self, action: #selector(selectorAllBtn), for: .touchUpInside)
sendButton.addTarget(self, action: #selector(selectorSendButton), for: .touchUpInside)
#objc func selectorAllBtn(_ sender : Any) {
}
#objc func selectorSendButton(_ sender : Any) {
}
You can try this code.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "headerView")
if headerView == nil {
headerView = UITableViewHeaderFooterView(reuseIdentifier: "headerView")
let button1 = UIButton(frame: CGRect(x: 8, y: 8, width: 80, height: 40))
button1.setTitle("Select", for: .normal)
button1.addTarget(self, action: #selector(self.buttonAction), for: .touchUpInside)
headerView?.addSubview(button1)
}
return headerView
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50 // set a height for header view
}
#objc func buttonAction(_ sender: UIButton) {
// write your code...
}

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.

Button in tableViewheader doesn't recognize header no. 0

I have this problem, hope you can help me out.
This is the code I have in viewForHeaderInSection :
let button = UIButton(frame: CGRect(x: view.frame.width - (cancel.frame.width + xImage.frame.width + 100), y: view.frame.origin.y, width: cancel.frame.width + xImage.frame.width + 120, height: view.frame.height))
button.backgroundColor = UIColor.blue.withAlphaComponent(0.5)
button.addTarget(self, action: #selector(action), for: .touchUpInside)
view.addSubview(button)
and this is action func:
#objc func action(sender: UIButton) {
let position: CGPoint = sender.convert(CGPoint.zero, to: self.tableView)
if let indexPath = self.tableView.indexPathForRow(at: position) {
let section = indexPath.section
print(section)
}
}
Now if I tap on every header except the first one (header 0) it prints the correct section.
How to make it to detect the header 0 too?
If you want to know which is the button's section, you might assign the section to the button's tag, eg:
in your viewForHeaderInSection
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let button = UIButton(frame: CGRect(x: view.frame.width - (cancel.frame.width + xImage.frame.width + 100), y: view.frame.origin.y, width: cancel.frame.width + xImage.frame.width + 120, height: view.frame.height))
button.backgroundColor = UIColor.blue.withAlphaComponent(0.5)
button.addTarget(self, action: #selector(action), for: .touchUpInside)
view.addSubview(button)
button.tag = section // this is the trick
}
and then inside the action:
#objc func action(sender: UIButton) {
let section = sender.tag
print(section)
}

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