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...
}
Related
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
I'm trying to add a floating action button (not a floating menu button) which will navigate me to the next view controller with a single click. I'm not getting the floating button right. I have tried the below code and it is not showing the appropriate button on the table view as it is getting scrolled along with the table. Is there any way to stick the button at the same place without getting scrolled along with the table?
func floatingButton(){
let btn = UIButton(type: .custom)
btn.frame = CGRect(x: 285, y: 485, width: 100, height: 100)
btn.setTitle("All Defects", for: .normal)
btn.backgroundColor = #colorLiteral(red: 0.1764705926, green: 0.4980392158, blue: 0.7568627596, alpha: 1)
btn.clipsToBounds = true
btn.layer.cornerRadius = 50
btn.layer.borderColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
btn.layer.borderWidth = 3.0
btn.addTarget(self,action: #selector(DestinationVC.buttonTapped), for: UIControlEvent.touchUpInside)
view.addSubview(btn)
}
All subviews added to UITableView will automatically scroll with it.
What you can do is add the button to the application Window, just remember to remove it when the ViewController disappears.
var btn = UIButton(type: .custom)
func floatingButton(){
btn.frame = CGRect(x: 285, y: 485, width: 100, height: 100)
btn.setTitle("All Defects", for: .normal)
btn.backgroundColor = #colorLiteral(red: 0.1764705926, green: 0.4980392158, blue: 0.7568627596, alpha: 1)
btn.clipsToBounds = true
btn.layer.cornerRadius = 50
btn.layer.borderColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
btn.layer.borderWidth = 3.0
btn.addTarget(self,action: #selector(DestinationVC.buttonTapped), for: UIControlEvent.touchUpInside)
if let window = UIApplication.shared.keyWindow {
window.addSubview(btn)
}
}
and in viewWillDisappear:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
btn.removeFromSuperview()
}
For iOS 13 and above you can check for the key window using this extension:
extension UIWindow {
static var key: UIWindow? {
if #available(iOS 13, *) {
return UIApplication.shared.windows.first { $0.isKeyWindow }
} else {
return UIApplication.shared.keyWindow
}
}
}
Here's a working example on XCode 10 with Swift 4.2.
Note that the FAB button will disappear when the view disappears, and reappears when the controller is loaded again.
import UIKit
class ViewController: UITableViewController {
lazy var faButton: UIButton = {
let button = UIButton(frame: .zero)
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = .blue
button.addTarget(self, action: #selector(fabTapped(_:)), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
}
override func viewDidAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let view = UIApplication.shared.keyWindow {
view.addSubview(faButton)
setupButton()
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let view = UIApplication.shared.keyWindow, faButton.isDescendant(of: view) {
faButton.removeFromSuperview()
}
}
func setupTableView() {
tableView.backgroundColor = .darkGray
}
func setupButton() {
NSLayoutConstraint.activate([
faButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -36),
faButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -36),
faButton.heightAnchor.constraint(equalToConstant: 80),
faButton.widthAnchor.constraint(equalToConstant: 80)
])
faButton.layer.cornerRadius = 40
faButton.layer.masksToBounds = true
faButton.layer.borderColor = UIColor.lightGray.cgColor
faButton.layer.borderWidth = 4
}
#objc func fabTapped(_ button: UIButton) {
print("button tapped")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 5
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 64
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 32
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return UIView()
}
}
If you currently using tableViewController then no , you must subclass UIViewController add UItableView and your floating button to it
Or you may override scollviewDidScroll and change button y according to tableview current offset
drag scrollview as IBOutlet and set it's delegate to the viewController
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let off = scrollView.contentOffset.y
btn.frame = CGRect(x: 285, y: off + 485, width: btn.frame.size.width, height: btn.frame.size.height)
}
code snapshot
in action
see in action
There is a way that is worked for me. In my table view controller, defined a button first, then override the function scrollViewDidScroll(), like this:
import UIKit
class MyTableViewController: UITableViewController {
private let button = UIButton(type: UIButton.ButtonType.custom) as UIButton
override func viewDidLoad() {
let bottomImage = UIImage(named: "yourImage.png")
let yPst = self.view.frame.size.height - 55 - 20
button.frame = CGRect(x: 12, y: yPst, width: 55, height: 55)
button.setImage(bottomImage, for: .normal)
button.autoresizingMask = [.flexibleTopMargin, .flexibleRightMargin]
button.addTarget(self, action: #selector(buttonClicked(_:)), for:.touchUpInside)
button.layer.shadowRadius = 3
button.layer.shadowColor = UIColor.lightGray.cgColor
button.layer.shadowOpacity = 0.9
button.layer.shadowOffset = CGSize.zero
button.layer.zPosition = 1
view.addSubview(button)
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
let off = self.tableView.contentOffset.y
let yPst = self.view.frame.size.height
button.frame = CGRect(x: 12, y:off + yPst, width: button.frame.size.width, height: button.frame.size.height)
}
#objc private func buttonClicked(_ notification: NSNotification) {
// do something when you tapped the button
}
}
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)
}
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)
hello I want to add two buttons on my ViewController programmatically like this
What I have done is this
func createButton(buttonTitle: String,buttonAction: Selector) -> UIButton{
let button = UIButton(type: UIButtonType.System) as UIButton
button.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame)/2, 48)
// button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(buttonTitle, forState: UIControlState.Normal)
button.addTarget(self, action:buttonAction, forControlEvents: UIControlEvents.TouchUpInside)
button.setTitleColor(UIColor.whiteColor(), forState:UIControlState.Normal)
button.titleLabel?.font = UIFont(name: Variables.MONTESERRAT_REGULAR, size: 20.0)
button.backgroundColor = UIColor().blueColor() //top
button.titleEdgeInsets = UIEdgeInsetsMake(0.0,10.0, 10.0, 0.0)
return button
}
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 48)
bottomButton = createButton("PUBLISH", buttonAction: "Publish")
footerView.addSubview(bottomButton!)
return footerView
}
At the moment it only prints one button. for second button I am doing this
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 48)
bottomButton = createButton("PUBLISH", buttonAction: "Publish")
bottomButton2 = createButton("Delete", buttonAction: "Delete")
footerView.addSubview(bottomButton!)
footerView.addSubview(bottomButton2!)
return footerView
}
This code is not printing two buttons. just printing only one
I think the problem is that both buttons have the same position, so one is showing above the other.
Try this:
func createButton(buttonTitle: String,buttonAction: Selector, buttonNumber : Int) -> UIButton{
let backgroundColor = buttonNumber == 0 ? UIColor.blueColor() : UIColor.orangeColor()
let space : CGFloat = 5
let button = UIButton(type: UIButtonType.System) as UIButton
let width = (CGRectGetWidth(self.view.frame) - space)/2
let xPos = buttonNumber == 0 ? 0 : width + space
button.frame = CGRectMake(xPos, 0, width, 48)
// button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(buttonTitle, forState: UIControlState.Normal)
button.addTarget(self, action:buttonAction, forControlEvents: UIControlEvents.TouchUpInside)
button.setTitleColor(UIColor.whiteColor(), forState:UIControlState.Normal)
// button.titleLabel?.font = UIFont(name: Variables.MONTESERRAT_REGULAR, size: 20.0)
button.backgroundColor = backgroundColor
button.titleEdgeInsets = UIEdgeInsetsMake(0.0,10.0, 10.0, 0.0)
return button
}
And then add it like so:
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 48)
bottomButton = createButton("PUBLISH", buttonAction: "Publish", buttonNumber: 0)
bottomButton2 = createButton("Delete", buttonAction: "Delete", buttonNumber: 1)
footerView.addSubview(bottomButton!)
footerView.addSubview(bottomButton2!)
return footerView
}