I have a search controller added to navigationController.searchController. When the screen initially loads there is a black space above the navigation bar. Only when I tap on the search bar this space correctly shows white. When I tap off the search bar, this area shows black again.
import UIKit
import Foundation
import InstantSearch
class AlgoliaViewController: UIViewController, UISearchBarDelegate {
let userHitsInteractor: HitsInteractor<User> = .init(infiniteScrolling: .off, showItemsOnEmptyQuery: false)
let businessHitsInteractor: HitsInteractor<Business> = .init(infiniteScrolling: .off, showItemsOnEmptyQuery: false)
let multiSearch = MultiIndexSearcher(appID: APP_ID, apiKey: APP_KEY, indexNames: ["dev_USERS","dev_BUSINESS"])
lazy var multiConnector: MultiIndexSearchConnector = .init(searcher: multiSearch, indexModules: [
.init(indexName: "dev_USERS",
hitsInteractor: userHitsInteractor),
.init(indexName: "dev_BUSINESS",
hitsInteractor: businessHitsInteractor)
], searchController: searchController, hitsController: hitsTableViewController)
lazy var searchController: UISearchController = .init(searchResultsController: hitsTableViewController)
let hitsTableViewController = MultiIndexController()
let statsInteractor: StatsInteractor = .init()
override func viewDidLoad() {
super.viewDidLoad()
multiConnector.connect()
multiSearch.search()
statsInteractor.connectController(self)
setupUI()
}
func setupUI() {
view.backgroundColor = .white
navigationItem.searchController = searchController
navigationController?.navigationBar.backgroundColor = .white
// navigationItem.titleView = searchController.searchBar
navigationController?.navigationBar.backgroundColor = .white
navigationController?.navigationBar.isTranslucent = false
navigationController?.hidesBarsOnSwipe = false
searchController.hidesNavigationBarDuringPresentation = false
searchController.showsSearchResultsController = true
searchController.automaticallyShowsCancelButton = false
searchController.searchBar.delegate = self
searchController.obscuresBackgroundDuringPresentation = false
hitsTableViewController.view.backgroundColor = .white
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
searchController.isActive = true
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
searchController.isActive = false
}
}
extension AlgoliaViewController: StatsTextController {
func setItem(_ item: String?) {
title = item
}
}
class MultiIndexController: UITableViewController, MultiIndexHitsController {
var hitsSource: MultiIndexHitsSource?
let cellID = "cellID"
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(ResultsItemCell.self, forCellReuseIdentifier: cellID)
setupUI()
self.tableView.keyboardDismissMode = .onDrag
}
func setupUI() {
view.backgroundColor = .white
tableView.backgroundColor = .white
tableView.separatorStyle = .none
}
override func numberOfSections(in tableView: UITableView) -> Int {
return (hitsSource?.numberOfSections())!
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (hitsSource?.numberOfHits(inSection: section)) ?? 0
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 50))
let sectionTitle = UILabel(frame: CGRect(x: 0, y: 0, width: headerView.frame.width, height: headerView.frame.height))
Utilities.styleLblFont(sectionTitle, fontName: "Cabin-SemiBold", fontSize: 18, color: .black)
var headertitle = ""
switch section {
case 0:
print("section 0")
headertitle = "People"
case 1:
print("section 1")
headertitle = "Businesses"
default:
break
}
headerView.backgroundColor = .white
sectionTitle.text = headertitle
headerView.addSubview(sectionTitle)
return headerView
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as! ResultsItemCell
switch indexPath.section {
case 0:
if let item: User = try? hitsSource?.hit(atIndex: indexPath.row, inSection: indexPath.section) {
cell.nameLbl.text = item.userName
cell.avatar.loadImage(item.profilePhotoUrl)
cell.jobTitleLbl.text = item.userType
}
case 1:
if let business: Business = try? hitsSource?.hit(atIndex: indexPath.row, inSection: indexPath.section) {
cell.nameLbl.text = business.businessName
cell.avatar.loadImage(business.businessAvatarUrl)
cell.jobTitleLbl.text = business.mission
}
default:
break
}
return cell
}
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 50))
let seeResultsBtn = UIButton(frame: CGRect(x: 0, y: 0, width: footerView.frame.width, height: footerView.frame.height))
var footerTitle = ""
switch section {
case 0:
footerTitle = "See all people"
case 1:
footerTitle = "See all businesses"
default:
footerTitle = "See all results"
}
footerView.addSubview(seeResultsBtn)
seeResultsBtn.translatesAutoresizingMaskIntoConstraints = false
seeResultsBtn.centerYAnchor.constraint(equalTo: footerView.centerYAnchor).isActive = true
seeResultsBtn.centerXAnchor.constraint(equalTo: footerView.centerXAnchor).isActive = true
Utilities.buttonTitle(seeResultsBtn, title: footerTitle, titleColour: .jabiMain, fontName: "Cabin-Medium", fontSize: 16)
footerView.backgroundColor = .white
return footerView
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 50
}
}
Please see the screenshots:
Related
I am using the section header of the tableview.
https://www.youtube.com/watch?v=U3gqR4dRiT8
If you look at it, almost at the end
When the section header goes up, the existing top section header goes up and collides and disappears.
And the text in the top section header is changed and floats
But when I run the sample, the text changes.
It doesn't seem to have the effect of pushing up the section header.
What should I do?
import UIKit
class MyTableviewControllerTableViewController: UITableViewController {
private let numberOfSections = 3
var meat = ["Beef","Turkey","Fish", "Lamb", "Chicken", "Pork", "Beef","Turkey","Fish", "Lamb", "Chicken", "Pork"]
var fruit = ["Apple","Banana","Cherry","Apple","Banana","Cherry","Apple","Banana","Cherry"]
var vegetable = ["Lettuce","Broccoli","Cauliflower","Lettuce","Broccoli","Cauliflower","Lettuce","Broccoli","Cauliflower"]
override func viewDidLoad() {
super.viewDidLoad()
// make the header sticky
self.automaticallyAdjustsScrollViewInsets = false
}
// MARK: - Table view data source
// return the number of sections
override func numberOfSections(in tableView: UITableView) -> Int {
return numberOfSections
}
// return the number of rows in the specified section
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var rowCount = 0
switch (section) {
case 0:
rowCount = meat.count
case 1:
rowCount = fruit.count
case 2:
rowCount = vegetable.count
default:
rowCount = 0
}
return rowCount
}
// Content Cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath)
switch (indexPath.section) {
case 0:
cell.textLabel?.text = meat[indexPath.row]
case 1:
cell.textLabel?.text = fruit[indexPath.row]
case 2:
cell.textLabel?.text = vegetable[indexPath.row]
default:
cell.textLabel?.text = "Other"
}
return cell
}
// Header Cell
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell") as! CustomTableViewHeaderCell
headerCell.backgroundColor = UIColor.gray
switch (section) {
case 0:
headerCell.headerLabel.text = "Meat";
case 1:
headerCell.headerLabel.text = "Fruit";
case 2:
headerCell.headerLabel.text = "Vegetable";
default:
headerCell.headerLabel.text = "Other";
}
return headerCell
}
// Footer Cell
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let rect = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: tableView.frame.size.width, height: 20))
let footerView = UIView(frame: rect)
footerView.backgroundColor = UIColor.darkGray
return footerView
}
// footer height
override func tableView(_ : UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 20.0
}
You can do it programmatically, and the result is perfect... Declare your table view and carry under your UIViewController (Attention, it's No UITableViewController) class:
class YourControllerClass: UIViewController {
let tableView = UITableView()
let cellId = "cellId"
let headerId = "headerId"
var meat = ["Beef","Turkey","Fish", "Lamb", "Chicken", "Pork", "Beef","Turkey","Fish", "Lamb", "Chicken", "Pork"]
var fruit = ["Apple","Banana","Cherry","Apple","Banana","Cherry","Apple","Banana","Cherry"]
var vegetable = ["Lettuce","Broccoli","Cauliflower","Lettuce","Broccoli","Cauliflower","Lettuce","Broccoli","Cauliflower"]
now in viewDidLoad configure nav bar and set tableview attributes and constraints:
override func viewDidLoad() {
super.viewDidLoad()
configureNavigationBar(largeTitleColor: .yourPreferColor, backgoundColor: .ultraDark, tintColor: .fuxiaRed, title: "My Title", preferredLargeTitle: true) // I use my function to configure navBar
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
tableView.register(HeaderCell.self, forCellReuseIdentifier: headerId)
tableView.backgroundColor = .yourPreferColor
tableView.delegate = self
tableView.dataSource = self
tableView.separatorColor = UIColor(white: 1, alpha: 0.2)
tableView.tableFooterView = UIView()
tableView.translatesAutoresizingMaskIntoConstraints = false
if #available(iOS 11.0, *) {
tableView.contentInsetAdjustmentBehavior = .never
} else {
automaticallyAdjustsScrollViewInsets = false
}
if #available(iOS 15.0, *) {
tableView.sectionHeaderTopPadding = 0
tableView.sectionFooterHeight = 0
} else {
UITableView.appearance().sectionHeaderTopPadding = CGFloat(0)
UITableView.appearance().sectionFooterHeight = CGFloat(0)
}
view.addSubview(tableView)
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
Now create an extension for tableView delegate and datasource:
extension NavBarAppearenceController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50 // header height
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
let headerCell = tableView.dequeueReusableCell(withIdentifier: headerId) as! HeaderCell // header cell
headerCell.translatesAutoresizingMaskIntoConstraints = false
headerView.addSubview(headerCell)
headerCell.topAnchor.constraint(equalTo: headerView.topAnchor).isActive = true
headerCell.leadingAnchor.constraint(equalTo: headerView.leadingAnchor).isActive = true
headerCell.trailingAnchor.constraint(equalTo: headerView.trailingAnchor).isActive = true
headerCell.bottomAnchor.constraint(equalTo: headerView.bottomAnchor).isActive = true
switch section {
case 0:
headerCell.label.text = "Meat"
case 1:
headerCell.label.text = "Fruit"
default:
headerCell.label.text = "Vegetables"
}
return headerView
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return meat.count
case 1:
return fruit.count
case 2:
return vegetable.count
default:
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let mySection = indexPath.section
switch mySection {
case 0:
cell.textLabel?.text = "\(meat[indexPath.row])"
case 1:
cell.textLabel?.text = "\(fruit[indexPath.row])"
default:
cell.textLabel?.text = "\(vegetable[indexPath.row])"
}
cell.contentView.backgroundColor = .yourPreferColor
cell.textLabel?.textColor = .white
cell.selectionStyle = .none
return cell
}
}
Create your custom header cell:
class HeaderCell: UITableViewCell {
let myView: UIView = {
let v = UIView()
v.backgroundColor = .yourPreferColor
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
let label = UILabel()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.backgroundColor = .yourPreferColor
label.textColor = .white
label.font = .systemFont(ofSize: 20, weight: .bold)
label.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(myView)
myView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
myView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
myView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
myView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
myView.addSubview(label)
label.topAnchor.constraint(equalTo: myView.topAnchor).isActive = true
label.leadingAnchor.constraint(equalTo: myView.leadingAnchor).isActive = true
label.trailingAnchor.constraint(equalTo: myView.trailingAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: myView.bottomAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
This is the result:
BONUS
This is my navBar configuration func:
func configureNavigationBar(largeTitleColor: UIColor, backgoundColor: UIColor, tintColor: UIColor, title: String, preferredLargeTitle: Bool) {
if #available(iOS 13.0, *) {
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithOpaqueBackground()
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: largeTitleColor]
navBarAppearance.titleTextAttributes = [.foregroundColor: largeTitleColor]
navBarAppearance.backgroundColor = backgoundColor
navigationController?.navigationBar.standardAppearance = navBarAppearance
navigationController?.navigationBar.compactAppearance = navBarAppearance
navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
navigationController?.navigationBar.prefersLargeTitles = preferredLargeTitle
navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.tintColor = tintColor
navigationItem.title = title
} else {
// Fallback on earlier versions
navigationController?.navigationBar.barTintColor = backgoundColor
navigationController?.navigationBar.tintColor = tintColor
navigationController?.navigationBar.isTranslucent = false
navigationItem.title = title
}
}
Expanding and Collapsing is working fine tableview, Only facing issue while didselect row is tapped, I'm getting same index evry time after selecting a row. I'm getting the same out put, I want to pass the data to next view but output isn't working properly.
Here's My Details...
My OutPut
My Model
struct ItemList {
var name: String
var items: [String]
var collapsed: Bool
init(name: String, items: [String], collapsed: Bool = false) {
self.name = name
self.items = items
self.collapsed = collapsed
}
}
My ViewController Class
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var sections = [ItemList]()
var items: [ItemList] = [
ItemList(name: "Mac", items: ["MacBook", "MacBook Air"]),
ItemList(name: "iPad", items: ["iPad Pro", "iPad Air 2"]),
ItemList(name: "iPhone", items: ["iPhone 7", "iPhone 6"])
]
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
}
TableView Extension
extension ViewController:UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 60
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerHeading = UILabel(frame: CGRect(x: 5, y: 10, width: self.view.frame.width, height: 40))
let imageView = UIImageView(frame: CGRect(x: self.view.frame.width - 30, y: 20, width: 20, height: 20))
if items[section].collapsed{
imageView.image = UIImage(named: "collapse")
}else{
imageView.image = UIImage(named: "expand")
}
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 60))
let tapGuesture = UITapGestureRecognizer(target: self, action: #selector(headerViewTapped))
tapGuesture.numberOfTapsRequired = 1
headerView.addGestureRecognizer(tapGuesture)
headerView.backgroundColor = UIColor.red
headerView.tag = section
headerHeading.text = items[section].name
headerHeading.textColor = .white
headerView.addSubview(headerHeading)
headerView.addSubview(imageView)
return headerView
}
func numberOfSections(in tableView: UITableView) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
let itms = items[section]
return !itms.collapsed ? 0 : itms.items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
cell.textLabel?.text = items[indexPath.section].items[indexPath.row]
return cell
}
#objc func headerViewTapped(tapped:UITapGestureRecognizer){
print(tapped.view?.tag)
if items[tapped.view!.tag].collapsed == true{
items[tapped.view!.tag].collapsed = false
}else{
items[tapped.view!.tag].collapsed = true
}
if let imView = tapped.view?.subviews[1] as? UIImageView{
if imView.isKind(of: UIImageView.self){
if items[tapped.view!.tag].collapsed{
imView.image = UIImage(named: "collapsed")
}else{
imView.image = UIImage(named: "expand")
}
}
}
tableView.reloadData()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let row = items[indexPath.row]
print("IndexPath :- \(row.name)")
}
}
If you look at the way you are setting the text in your cells in cellForRowAt:
cell.textLabel?.text = items[indexPath.section].items[indexPath.row]
You are saying:
get the ItemList object for indexPath.section from items array
get the String from that object's items array of this indexPath.row
However, in your didSelectRowAt:
let row = items[indexPath.row]
print("IndexPath :- \(row.name)")
You are saying:
get the ItemList object for indexPath.row from items array
print the .name property of that object
So, change your didSelectRowAt code to match your cellForRowAt logic:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedString = items[indexPath.section].items[indexPath.row]
print("IndexPath :- \(selectedString)")
// or, for a little more clarity
let sectionObject = items[indexPath.section]
let rowItem = sectionObject.items[indexPath.row]
print("IndexPath :- \(indexPath) // Section :- \(sectionObject.name) // Item :- \(rowItem)")
}
I'm setting up a collapsable tableView, but something strange happens on the collapsable item. When you look at the video keep an eye on the "Where are you located" line.. (I'm using a .plist for the question and answer items)
Where do I go wrong, is it somewhere in my code? I don't want to let that line stick on the top :(
Here is the code I'm using but I can't find anything strange...
class FAQViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var questionsArray = [String]()
var answersDict = Dictionary<String, [String]>() // multiple answers for a question
var collapsedArray = [Bool]()
#IBOutlet weak var tableView: UITableView!
override func viewWillAppear(_ animated: Bool) {
// Hide the navigation bar on the this view controller
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
addTableStyles()
readQAFile()
tableView.delegate = self
tableView.dataSource = self
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
}
func addTableStyles(){
navigationController?.isNavigationBarHidden = false
self.tableView?.backgroundView = {
let view = UIView(frame: self.tableView.bounds)
return view
}()
tableView.estimatedRowHeight = 43.0;
tableView.rowHeight = UITableView.automaticDimension
tableView.separatorStyle = UITableViewCell.SeparatorStyle.singleLine
}
func readQAFile(){
guard let url = Bundle.main.url(forResource: "QA", withExtension: "plist")
else { print("no QAFile found")
return
}
let QAFileData = try! Data(contentsOf: url)
let dict = try! PropertyListSerialization.propertyList(from: QAFileData, format: nil) as! Dictionary<String, Any>
// Read the questions and answers from the plist
questionsArray = dict["Questions"] as! [String]
answersDict = dict["Answers"] as! Dictionary<String, [String]>
// Initially collapse every question
for _ in 0..<questionsArray.count {
collapsedArray.append(false)
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return questionsArray.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if collapsedArray[section] {
let ansCount = answersDict[String(section)]!
return ansCount.count
}
return 0
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
// Set it to any number
return 70
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 1
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if collapsedArray[indexPath.section] {
return UITableView.automaticDimension
}
return 2
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRect(x:0, y:0, width:tableView.frame.size.width, height:40))
headerView.tag = section
let headerString = UILabel(frame: CGRect(x: 10, y: 10, width: tableView.frame.size.width, height: 50)) as UILabel
headerString.text = "\(questionsArray[section])"
headerView .addSubview(headerString)
let headerTapped = UITapGestureRecognizer (target: self, action:#selector(sectionHeaderTapped(_:)))
headerView.addGestureRecognizer(headerTapped)
return headerView
}
#objc func sectionHeaderTapped(_ recognizer: UITapGestureRecognizer) {
let indexPath : IndexPath = IndexPath(row: 0, section:recognizer.view!.tag)
if (indexPath.row == 0) {
let collapsed = collapsedArray[indexPath.section]
collapsedArray[indexPath.section] = !collapsed
//reload specific section animated
let range = Range(NSRange(location: indexPath.section, length: 1))!
let sectionToReload = IndexSet(integersIn: range)
self.tableView.reloadSections(sectionToReload as IndexSet, with:UITableView.RowAnimation.fade)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cellIdentifier = "Cell"
let cell: UITableViewCell! = self.tableView.dequeueReusableCell(withIdentifier: cellIdentifier)
cell.textLabel?.adjustsFontSizeToFitWidth = true
cell.textLabel?.numberOfLines = 0
let manyCells : Bool = collapsedArray[indexPath.section]
if (manyCells) {
let content = answersDict[String(indexPath.section)]
cell.textLabel?.text = content![indexPath.row]
}
return cell
}
override var prefersStatusBarHidden: Bool {
return true
}
}
You need to change the style of the tableView to grouped, when you initialize it:
let tableView = UITableView(frame: someFrame, style: .grouped)
or from Storyboard:
After that you will have this issue, which I solved by setting a tableHeaderView to the tableView that has CGFloat.leastNormalMagnitude as its height:
override func viewDidLoad() {
super.viewDidLoad()
var frame = CGRect.zero
frame.size.height = .leastNormalMagnitude
tableView.tableHeaderView = UIView(frame: frame)
}
Just remove your headerView from view hierarchy here
#objc func sectionHeaderTapped(_ recognizer: UITapGestureRecognizer) {
headerView.removeFromSuperview()
...
}
By the way, yes creating a openable tableview menu with using plist is one of the methods but it could be more simple. In my opinion you should refactor your code.
I have an UIImageView inside my table view cell, named pic. I want to use an array named colors (filled with UIImages), to display on 3 tableview cells.
I have the ViewController class and the tableview cell class listed below. The tableview displays the imageview pic. I assume you would place the color array in cellForRowAt method.
import UIKit
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
var colors:[UIImage] = [
UIImage(named: "blue")!,
UIImage(named: "red")!,
UIImage(named: "red")!
]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 118
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! customtv
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
class customtv: UITableViewCell {
lazy var backView : UIView = {
let view = UIView(frame: CGRect(x: 10, y: 6, width: self.frame.width , height: 110))
view.backgroundColor = .green
return view
}()
lazy var pic : UIImageview = {
let view = UIImageview(frame: CGRect(x: 100, y: 6, width: 100 , height: 100))
view.backgroundColor = .red
return view
}()
override func layoutSubviews() {
backView.clipsToBounds = true
backView.frame = CGRect(x: 0, y: 6, width: bounds.maxX , height: 110)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(animated, animated: true)
addSubview(backView)
addSubview(pic)
}
}
Try with this example below
import UIKit
class ViewController1: UIViewController {
var tableView: UITableView?
var colors:[UIImage] = [
UIImage(named: "blue")!,
UIImage(named: "red")!,
UIImage(named: "red")!
]
override func viewDidLoad() {
super.viewDidLoad()
loadUI()
}
func loadUI() {
tableView = UITableView()
self.view.addSubview(tableView.unsafelyUnwrapped)
tableView?.register(CustomTVC.self, forCellReuseIdentifier: "cell")
tableView?.delegate=self
tableView?.dataSource=self
tableView?.translatesAutoresizingMaskIntoConstraints = false
tableView?.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
tableView?.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
tableView?.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
tableView?.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
}
extension ViewController1: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 118
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTVC
cell.pic.image = colors[indexPath.row]
return cell
}
}
class CustomTVC: UITableViewCell {
lazy var backView : UIView = {
let view = UIView()
view.backgroundColor = .green
return view
}()
lazy var pic : UIImageView = {
let view = UIImageView()
view.backgroundColor = .red
return view
}()
override func awakeFromNib() {
super.awakeFromNib()
commonInit()
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override func layoutSubviews() {
backView.clipsToBounds = true
backView.frame = CGRect(x: 0, y: 6, width: bounds.maxX , height: 110)
}
func commonInit() {
contentView.addSubview(backView)
backView.translatesAutoresizingMaskIntoConstraints = false
backView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4).isActive = true
backView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 4).isActive = true
backView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -4).isActive = true
backView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -4).isActive = true
backView.addSubview(pic)
pic.translatesAutoresizingMaskIntoConstraints = false
pic.topAnchor.constraint(equalTo: backView.topAnchor, constant: 4).isActive = true
pic.leftAnchor.constraint(equalTo: backView.leftAnchor, constant: 4).isActive = true
pic.bottomAnchor.constraint(equalTo: backView.bottomAnchor, constant: -4).isActive = true
pic.widthAnchor.constraint(equalTo: pic.heightAnchor).isActive = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(animated, animated: true)
}
}
I have searched for hours trying stackOverFlows solutions to this issue!!! All of which cause my custom UITable Cells to overlap and not space out. I just want my spacing to be automatic like 'return UITableView.automaticDimension' but say + 8 so that my custom cells aren't right next to each other. I cannot figure it out and maybe it is because I have one line of code that I shouldn't.
This is my cocoa touch class that creates my custom cell 'DiscussionTableViewCell':
class DiscussionTableViewCell: UITableViewCell {
lazy var backView: UIView = {
let view = UIView(frame: CGRect(x: 10, y: 6, width: UIScreen.main.bounds.width - 20, height: 55))
view.backgroundColor = UIColor.rgb(r: 194, g: 208, b: 242)
//view.layer.borderWidth = 3
return view
}()
lazy var discussionTitleLabel: UILabel = {
let LDiscussionTitleLabel = UILabel(frame: CGRect(x: 4, y: 6, width: backView.frame.width - 116, height: 30))
LDiscussionTitleLabel.textAlignment = .left
LDiscussionTitleLabel.font = UIFont.boldSystemFont(ofSize: 18)
return LDiscussionTitleLabel
}()
lazy var discussionDescriptionLabel: UILabel = {
let LDiscussionDescriptionLabel = UILabel(frame: CGRect(x: 4, y: 27, width: backView.frame.width - 30, height: 30))
LDiscussionDescriptionLabel.textAlignment = .left
LDiscussionDescriptionLabel.font = UIFont.systemFont(ofSize: 16)
LDiscussionDescriptionLabel.textColor = UIColor.gray
return LDiscussionDescriptionLabel
}()
override func awakeFromNib() {
super.awakeFromNib()
//layoutMargins = UIEdgeInsets(top: 8, left: 0, bottom: 8, right: 0)
// Initialization code
}
override func layoutSubviews() {
//super.layoutSubviews()
contentView.backgroundColor = UIColor.rgb(r: 203, g: 215, b: 242)
backgroundColor = UIColor.yellow
backView.layer.cornerRadius = 5
backView.clipsToBounds = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
addSubview(backView)
backView.addSubview(discussionTitleLabel)
backView.addSubview(discussionDescriptionLabel)
// Configure the view for the selected state
}
}
And a section of my ViewController that applies to assigning text to the table cell, and spacing between cells:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return discussionTitles.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! DiscussionTableViewCell
cell.discussionTitleLabel.text = discussionTitles[indexPath.row]
cell.discussionDescriptionLabel.text = discussionDescriptions[indexPath.row]
return cell
}
return UITableViewCell()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if (singlePageVar == 100) {
return 1407//UITableView.automaticDimension
}
return 62//UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("section: \(indexPath.section)")
print("row: \(indexPath.row)")
var topicNumberRow = (indexPath.row)
mainTopicNumberRow = topicNumberRow
DiscussionBoardTopicThread()
}
//function I call in viewdidload to show table
func setupDiscussionBoard() {
discussionBoardView.separatorStyle = .none
view.addSubview(discussionBoardView)
discussionBoardView.backgroundColor = UIColor(red: 203/255, green: 215/255, blue: 242/255, alpha: 1.0)
discussionBoardView.dataSource = self
discussionBoardView.delegate = self
discussionBoardView.translatesAutoresizingMaskIntoConstraints = false
discussionBoardView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
discussionBoardView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
discussionBoardView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
discussionBoardView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
discussionBoardView.register(DiscussionTableViewCell.self, forCellReuseIdentifier: "cell")
}
}