how to add table view footer with one label in swift 5 - swift

I want to add only one label at the end of the tableview.
let customView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
customView.backgroundColor = UIColor.red
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
label.text = "app version"
customView.addSubview(label)
sideMenuTableView.tableFooterView = customView
I want to set the customView width equal to main view's width and label should be at the left most corner of the view

Try this with mainView width
let customView = UIView(frame: CGRect(x: 0, y: 0, width: self.mainView.frame.size.width, height: 50))
customView.backgroundColor = UIColor.red
let label = UILabel(frame: CGRect(x: 0, y: 0, width: self.mainView.frame.size.width, height: 50))
label.text = "app version"
label.textAlignment = .left
customView.addSubview(label)
sideMenuTableView.tableFooterView = customView

Swift 5
Add UITableViewDelegate Methods:-
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 40))
footerView.backgroundColor = UIColor.yellow
let labelFooter = UILabel(frame: footerView.frame)
labelFooter.text = "Footer view label text."
labelFooter.textColor = .red
footerView.addSubview(labelFooter)
return footerView
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 40
}

Related

uiCollectionView inside a uiCollectionViewCell is not scrolling horizontally

Hey Everyone and thank you for taking your time to view this, I am trying to make a uiCollectionView scroll horizontally within a uiCollectionViewCell, the background and elements are showing but im unable to scroll, the uiCollectionViewcontaining the uiCollectionViewCell (which contains the uiCollectionView i need to scroll horizontally) in scrolling vertically as expected. Below are the relative classes:
The uiCollectionView and its uiCollectionViewCells which contains the uiCollectionView that needs horizontal scrolling, in the collectionView method the cases that needs scrolling are Prop4 and Countries:
lazy var collView: UICollectionView = {
let sub = SubclassedCollectionViewCell.self
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: self.view.frame.width, height:self.view.frame.height/100)
layout.scrollDirection = .vertical
// layout.minimumLineSpacing = 1000
layout.sectionInset = UIEdgeInsets(top:100, left: 0, bottom: 100, right: 0)
print("the frame",self.view.frame)
let view = UICollectionView(frame: CGRect(x:0, y:0, width: self.view.frame.width, height: self.view.frame.height), collectionViewLayout: layout)
view.register(sub, forCellWithReuseIdentifier: "profInfo")
view.backgroundColor = .clear
view.isUserInteractionEnabled = true
view.dataSource = self
view.delegate = self
return view
}()
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "profInfo", for: indexPath) as! SubclassedCollectionViewCell
myCell.isUserInteractionEnabled = true
myCell.frame = CGRect(x: 10, y: (indexPath.row+1)*75, width: Int(self.view.frame.width) - 10, height: 50)
myCell.backgroundColor = .clear
let v = UIView(frame: CGRect(x: 0, y: 0, width: 150, height: 50))
let v2 = UIView(frame: CGRect(x: 150, y: 0, width: Int(self.view.frame.width) - 160, height: 50))
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
let label2 = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
let imageV = UIImageView(frame: CGRect(x: 0, y: 12.5, width: 25, height: 25))
let imageV2 = UIImageView(frame: CGRect(x: 0, y: 12.5, width: 25, height: 25))
label.center = CGPoint(x: 150, y: 25)
label.textColor = .white
label2.textColor = .white
label2.center = CGPoint(x: 115, y: 25)
label2.textAlignment = .center
imageV2.center = CGPoint(x: 115, y: 25)
label.text = prof!.arrInfo[indexPath.row].title + ":"
print("array info", prof!.arrInfo)
switch(prof!.arrInfo[indexPath.row].title){
case "Prop1" :
imageV.image = UIImage(named: "art.scnassets/prop1.png")?.resized(to: CGSize(width: 10, height: 10))
label2.text = prof!.arrInfo[indexPath.row].text
v2.addSubview(label2)
break;
case "DOB" :
imageV.image = UIImage(named: "art.scnassets/DOB.png")?.resized(to: CGSize(width: 10, height: 10))
label2.text = getDOBFormat(dateStr: prof!.arrInfo[indexPath.row].text!)
v2.addSubview(label2)
break;
case "Prop3" :
imageV.image = UIImage(named: "art.scnassets/prop3.png")?.resized(to: CGSize(width: 10, height: 10))
imageV2.image = UIImage(named: prof!.arrInfo[indexPath.row].text!)?.resized(to: CGSize(width: 10, height: 10))
break;
case "Prop4" :
imageV.image = UIImage(named: "art.scnassets/prop4.png")?.resized(to: CGSize(width: 10, height: 10))
collectionViews[prof!.arrInfo[indexPath.row].title] = GeneralCollectionView()
collectionViews[prof!.arrInfo[indexPath.row].title]?.type = "Images"
collectionViews[prof!.arrInfo[indexPath.row].title]?.data = prof!.arrInfo[indexPath.row].selected
myCell.contentView.addSubview(collectionViews[prof!.arrInfo[indexPath.row].title]!.Container)
break;
case "Countries" :
imageV.image = UIImage(named: "art.scnassets/translation.png")?.resized(to: CGSize(width: 10, height: 10))
collectionViews[prof!.arrInfo[indexPath.row].title] = GeneralCollectionView()
collectionViews[prof!.arrInfo[indexPath.row].title]?.type = "Countries"
collectionViews[prof!.arrInfo[indexPath.row].title]?.data = prof!.arrInfo[indexPath.row].selected
myCell.contentView.addSubview(collectionViews[prof!.arrInfo[indexPath.row].title]!.Container)
break;
case "location":
imageV.image = UIImage(named: "art.scnassets/location.png")?.resized(to: CGSize(width: 10, height: 10))
label2.text = prof!.arrInfo[indexPath.row].text
v2.addSubview(label2)
break;
default:
break;
}
v.addSubview(label)
v.addSubview(imageV)
v2.addSubview(imageV2)
myCell.contentView.addSubview(v)
myCell.contentView.addSubview(v2)
return myCell
}
And this is the uiCollectionView that needs Horizontal scrolling and thats within the uiCollectionViewCell:
public class GeneralCollectionView:NSObject,UICollectionViewDelegate,UICollectionViewDataSource{
weak var parent:AnyObject?
var data:[String]?
var type:String?
lazy var Container: UICollectionView = {
let sub = SubclassedCollectionViewCell.self
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: 50, height:50)
layout.scrollDirection = .horizontal
let view = UICollectionView(frame: CGRect(x:150, y:0, width: 250, height: 50), collectionViewLayout: layout)
view.showsHorizontalScrollIndicator = false
view.isDirectionalLockEnabled = true
view.isScrollEnabled = true
view.isPagingEnabled = true
view.isUserInteractionEnabled = true
view.alwaysBounceHorizontal = true
view.clipsToBounds = true
view.translatesAutoresizingMaskIntoConstraints = false
view.register(sub, forCellWithReuseIdentifier: "myGenCell")
view.dataSource = self
view.delegate = self
view.backgroundColor = .white
layout.sectionInset = UIEdgeInsets(top:0, left: 10, bottom: 0, right: 10)
layout.minimumLineSpacing = 10 // space between rows
layout.minimumInteritemSpacing = 5 // space between items in the same
layout.itemSize = CGSize(width: 50, height: 50)
return view
}()
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data!.count
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "myGenCell", for: indexPath) as! SubclassedCollectionViewCell
myCell.isUserInteractionEnabled = true
if type == "Countries"{
let country = data![indexPath.item].split(separator: "-")
let label = UILabel()
label.frame.size = CGSize(width: 50, height: 50)
label.text = countryFlag(country: String(country[1]))
label.center = CGPoint(x: 30, y: 25)
myCell.contentView.addSubview(label)
print(label, countryFlag(country: String(country[1])))
} else {
let val = data![indexPath.item]
let imgView = UIImageView()
imgView.frame.size = CGSize(width: 20, height: 20)
imgView.image = UIImage(named: val)?.resized(to: CGSize(width: 25, height: 25))
imgView.center = CGPoint(x: 30, y: 25)
myCell.contentView.addSubview(imgView)
}
return myCell
}
}
It is because v2 is added after the horizontal collection view, therefore coming on top blocking all user interactions like your scroll gestures.
Give all your views different background colors to debug this sort of thing.
Set isUserInteractionEnabled = false to v2 and any other view blocking your scroll gestures.
Besides that,
Check out Modern collection views to get some examples of how to build a collection view.
Checkout Auto layout to properly size your views.

Unable to Format the Section Header of UITableView

One View Controller which has three Table Views in it. I am struggling with formatting and setting the section header for each table.My func for viewForHeaderInSection is attached below
My Goal is to achieve something like the image. Struggling to format and design the section header for each of the table views. Using the attached code get the Terminating app due to uncaught exception 'CALayerInvalid', reason: 'layer <CALayer: 0x12cc80610> is a part of cycle in its layer tree' error message
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if(tableView == firstTableView){
let button = UIButton(frame: CGRect(x: 270, y: 15, width:20 , height: 20))
button.tag = section
button.setImage(UIImage(named: "InfoIcon"), for: UIControl.State.normal)
button.addTarget(self,action:#selector(buttonClicked),for:.touchUpInside)
let view = UIView(frame: CGRect(x: 20, y: 8, width: tableView.frame.size.width, height: 30))
view.addSubview(button)
let label = UILabel(frame: CGRect(x: 12, y: 7, width: tableView.frame.size.width, height: 30))
label.font = UIFont.systemFont(ofSize: 24)
label.textColor = .white
label.text = "Learn More"
view.addSubview(label)
view.backgroundColor = UIColor.gray // Set your background color
}
else if (tableView == secondTableView) {
let button = UIButton(frame: CGRect(x: 270, y: 15, width:20 , height: 20))
button.tag = section
button.setImage(UIImage(named: "InfoIcon"), for: UIControl.State.normal)
button.addTarget(self,action:#selector(buttonClickedSecond),for:.touchUpInside)
let view = UIView(frame: CGRect(x: 20, y: 8, width: tableView.frame.size.width, height: 30))
view.addSubview(button)
let label = UILabel(frame: CGRect(x: 12, y: 7, width: tableView.frame.size.width, height: 30))
label.font = UIFont.systemFont(ofSize: 24)
label.textColor = .white
label.text = "Get Support"
view.addSubview(label)
view.backgroundColor = UIColor.gray
}
else if (tableView == thirdTableView)
{
let button = UIButton(frame: CGRect(x: 270, y: 15, width:20 , height: 20))
button.tag = section
button.setImage(UIImage(named: "InfoIcon"), for: UIControl.State.normal)
button.addTarget(self,action:#selector(buttonClickedThird),for:.touchUpInside)
let view = UIView(frame: CGRect(x: 20, y: 8, width: tableView.frame.size.width, height: 30))
view.addSubview(button)
let label = UILabel(frame: CGRect(x: 12, y: 7, width: tableView.frame.size.width, height: 30))
label.font = UIFont.systemFont(ofSize: 24)
label.textColor = .white
label.text = "Community"
view.addSubview(label)
view.backgroundColor = UIColor.gray
}
return view
}
Any help and assistance will be appreciated. Thanks!
In your viewForHeaderInSection func, you are creating a UIView object named view inside each if block. At the end of each if block, that object goes out-of-scope... it no longer exists.
Xcode doesn't give you a warning or error on this line:
return view
because view is an existing object of your controller.
This is one of the reasons it's a bad practice to use "built-in" object names for variables you are creating.
Change the top of your func to this:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView(frame: CGRect(x: 20, y: 8, width: tableView.frame.size.width, height: 30))
if(tableView == firstTableView){
// etc...
and remove that line from within each of your if blocks.
Better yet, change it to something like:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let myHeaderView = UIView(frame: CGRect(x: 20, y: 8, width: tableView.frame.size.width, height: 30))
if(tableView == firstTableView){
// etc... but change all instances of view. to myHeaderView.
} // end of last if block
return myHeaderView
}

Edit- how can I get UIlabel to get in the middle of the container?

how can i get UIlabel to get in the middle of the container? and that text and view disappear equally and come to the next view.
EDIT: This code is working fine for me now
class TestViewController: UIViewController {
let container = UIView()
let redSquare = UIView()
let blueSquare = UIView()
let label = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
self.label.textColor = UIColor.orange
self.label.font = label.font.withSize(25)
self.label.numberOfLines = 0
self.label.center = self.blueSquare.center
self.label.textAlignment = NSTextAlignment.center
self.label.text =
"sosdihfiosdfhsdhfdisfhsdfhdsoifhsdofhsdifhdsofhdsofhsdohdsfdosdohdfh"
self.blueSquare.addSubview(label)
self.label.frame = CGRect(x: 45, y: 120, width: 300, height: 100)
self.container.frame = CGRect(x: 7, y: 200, width: 400, height: 500)
self.view.addSubview(container)
self.redSquare.frame = CGRect(x: 0, y: 0, width: 400, height: 500)
self.blueSquare.frame = redSquare.frame
self.redSquare.backgroundColor = UIColor.darkGray
self.blueSquare.backgroundColor = UIColor.darkGray
self.container.addSubview(self.redSquare)
}
Define two labels like:
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 30))
let label2 = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 30))
then inside viewDidLoad() before adding redSquare to container fix some labels's property and add label's to blue and red square:
label.center = self.redSquare.center
label.textAlignment = NSTextAlignment.center
label.text = "same text"
label2.textAlignment = NSTextAlignment.center
label2.center = self.blueSquare.center
label2.text = "same text"
self.blueSquare.addSubview(label2)
self.redSquare.addSubview(label)

Making UITableView drop down with stackview

I am trying to achieve a UITableView drop down when I click on a button. Initially the tableView should be hidden, and when user presses button, it should drop down. I have been trying to achieve this with a UIStackView but to no success. Maybe I am doing it wrong or maybe there is another approach do do this.
let stackView = UIStackView()
var btn: UIButton!
var myTableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
myTableView.delegate = self
myTableView.dataSource = self
myTableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 1))
myTableView.frame = CGRect(x: 0, y: 0, width: 300, height: 200)
myTableView.center = CGPoint(x: self.view.frame.width/2, y: self.view.frame.height/2)
myTableView.showsVerticalScrollIndicator = false
btn = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 50))
btn.backgroundColor = UIColor.blue.withAlphaComponent(0.3)
btn.setTitle("DropDownMenu", for: UIControlState.normal)
btn.titleLabel?.textColor = .white
btn.titleLabel?.textAlignment = .center
btn.center = CGPoint(x: self.view.frame.width/2, y: myTableView.center.y - myTableView.frame.height/2 - btn.frame.height/2)
btn.addTarget(self, action: #selector(btnPressed), for: UIControlEvents.touchUpInside)
stackView.axis = UILayoutConstraintAxis.vertical
stackView.distribution = UIStackViewDistribution.equalSpacing
stackView.alignment = UIStackViewAlignment.center
stackView.spacing = 16.0
stackView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(btn)
stackView.addSubview(myTableView)
self.view.addSubview(stackView)
}
#objc func btnPressed() {
UIView.animate(withDuration: 1) {
self.myTableView.isHidden = !self.myTableView.isHidden
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "This is cell " + indexPath.row.description
cell.textLabel?.textColor = .black
return cell
}
I can get the tableView to disappear but with no animations. Any thoughts?
The approach I ended up taking was not going via a UIStackView but insead simply having a button that animates the tableView's frame. The frame is initially set to the width of the screen and a height of 0. When user presses button, I set the height.
UIView.animate(withDuration: 0.25, animations: {
self.menuTable.frame = CGRect(x: 0, y: (sender.center.y + sender.frame.height/2), width: self.view.frame.width, height: yourHeight)
})

UICollectionViewCell dashed border for dynamic cell width swift issue

Using UICollectionView under the UITableViewCell
Using below extension for creating dashed border:
extension UIView {
func addDashedLineView(frame: CGRect) {
let border = CAShapeLayer()
border.strokeColor = UIColor.blue.cgColor
border.lineDashPattern = [6, 6]
border.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)//self.frame
border.fillColor = UIColor.clear.cgColor
border.lineJoin = kCALineJoinRound
//print("widht: \(frame.width) fraheight: \(UIScreen.main.bounds.width)")
border.fillColor = nil
border.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: frame.width, height: frame.height), cornerRadius: 6).cgPath
self.clipsToBounds = true
self.layer.addSublayer(border)
}
}
Below is my collection view method where i am calling above method (actually the cell width depending upon the content size so i am calculating the text width) the issue is when the cell are dequeue from the list the border get redraw from different width, also i am using custom cell "CollectionViewCell" class:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: CollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
let width = self.collectionData[indexPath.row].width(withConstraintedHeight: 14, font: .systemFont(ofSize: 17)) + Constant.cellPadding
cell.contentView.addDashedLineView(frame: CGRect(x: 0, y: 0, width: width, height: Constant.itemHeight))
cell.contentView.setNeedsLayout()
cell.contentView.layoutIfNeeded()
cell.layoutIfNeeded()
return cell
}
When first load drawing border correctly when scroll the view it has been redraw
How to resolve the issue