How to customize a section of cell - ios

Is there a way to customize a section of cell? Probably the easiest way is to design a cell in the storyboard but I do not know how to implement it in my code.
This is what I got so far. It is pretty basic and copied from a tutorial on youtube. So sectionData should be replaced with the input for the customized section/subCell.
The upper cell should be the 'mainCell' and the cell below should be displayed after the mainCell is touched
import UIKit
struct cellData {
var opened = Bool()
var title = String()
var sectionData = [String]()
}
class ViewController: UITableViewController {
var tableViewData = [cellData]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableViewData = [cellData(opened: false, title: "Title1", sectionData: ["Cell1","Cell2","Cell3"]),
cellData(opened: false, title: "Title2", sectionData: ["Cell1","Cell2","Cell3"]),
cellData(opened: false, title: "Title3", sectionData: ["Cell1","Cell2","Cell3"]),
cellData(opened: false, title: "Title4", sectionData: ["Cell1","Cell2","Cell3"])]
}
override func numberOfSections(in tableView: UITableView) -> Int {
return tableViewData.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableViewData[section].opened == true {
return tableViewData[section].sectionData.count + 1
} else {
return 1
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let dataIndex = indexPath.row - 1
if indexPath.row == 0 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") else {return UITableViewCell()}
cell.textLabel?.text = tableViewData[indexPath.section].title
return cell
} else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") else {return UITableViewCell()}
cell.textLabel?.text = tableViewData[indexPath.row].sectionData[dataIndex]
return cell
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
if tableViewData[indexPath.section].opened == true {
tableViewData[indexPath.section].opened = false
let sections = IndexSet.init(integer: indexPath.section )
tableView.reloadSections(sections, with: .none)
} else {
tableViewData[indexPath.section].opened = true
let sections = IndexSet.init(integer: indexPath.section )
tableView.reloadSections(sections, with: .none)
}
}
}
}

https://www.appcoda.com/expandable-table-view/
you can follow this tutorial. You can reload the cell which you want to expand using below code. I have added in the `didSelectRowAt. Set expandCell variable to true for changing height of cell when reloading.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Expand View
self.expandCell = true
self.tableView.beginUpdates()
self.tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
self.tableView.endUpdates()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == expandRowIndex && self.expandCell {
return 200
}
return UITableViewAutomaticDimension
}
but the question you asked is irrelevant to the once you want to implement. anyway the answer for your question is, you can implement viewForHeaderInSection and viewForFooterInSection to customize your tableview sections.
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = "create your custom cell here or you can init from your nib"
return cell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 60
}
if you want to do it in storyboard, just drag and drop UITableViewCell inside your tableview, assign some reuserIdentifier. call this tableview cell in your viewForHeaderInSection

Related

Why cell is display overflow the table view in Swift

I have fix make the cell to cliptobounds in the table view and also assign constraints to fix the table position and height.
Below are some parts of my code.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if hiddenRow.contains(indexPath.row) || hiddenRow2.contains(indexPath.row){
rowHeight.append(300)
return 300 //Expanded
}
else{
rowHeight.append(120)
return 120 //Not Expanded
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "med_reusable_cell", for: indexPath as IndexPath) as! MedListTableViewCell
cell.backgroundColor = TRANSPARENT
cell.layer.cornerRadius = DEFAULT_CORNER_RADIUS
active_table_height.constant = self.view.frame.size.height * 11/36
expired_table_height.constant = self.view.frame.size.height * 11/36
cell overflow
The different between my code and others are
This is an expendable view cell which the height will be change based whether the cell is expended
I use a reusable cell for two tables.
How can I solve this?
You can achieve this by adding a header to each cell, then when you'll click it, reload the table view with the opened cell look at this example :
DataModel :
struct DataItem {
var isExpand: Bool
var title: String
var value:String
init(isExpand:Bool = false, title:String, value:String) {
self.isExpand = isExpand
self.title = title
self.value = value
}
}
Custom Header witch will listen to events :
protocol CustomHeaderViewDelegate: AnyObject {
func headerViewTap(_ section: Int)
}
class CustomHeaderView: UITableViewHeaderFooterView {
weak var delegate: CustomHeaderViewDelegate?
var sectionNumber: Int?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let gesture = UITapGestureRecognizer(target: self, action: #selector(CustomHeaderView.tableViewSectionTapped(_:)))
self.addGestureRecognizer(gesture)
}
#objc func tableViewSectionTapped(_ gesture: UIGestureRecognizer) {
if let sectionNumber = sectionNumber{
delegate?.headerViewTap(sectionNumber)
}
}
}
TableView and Custom Header delegates
extension ViewController : UITableViewDelegate, UITableViewDataSource{
//The number of sections fits the number of cells, the current list is an array of DataObject, holding a title and a content.
func numberOfSections(in tableView: UITableView) -> Int {
return self.currentList.count
}
//Each section(group of cells) contains one row
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as UITableViewCell
return cell
}
//update heights for row if the header has been taped
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let isExpanded = self.currentList[indexPath.section].isExpand
if isExpanded {
return UITableView.automaticDimension
}
return 0
}
//update the estimatedHeightForRowAt if the hader has been taped
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
let isExpanded = self.currentList[indexPath.section].isExpand
if isExpanded{
return UITableView.automaticDimension
}
return 0
}
//returns a custom header
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "Header") as! CustomHeaderView
return headerView
}
}
extension ViewController : CustomeHeaderViewDelegate{
func headerViewTap(_ section: Int) {
selectedItem = self.currentList[section]
let output = self.currentList.map({ (item:DataItem) -> DataItem in
var result = item
if result.title == self.selectedItem?.title{
result.isExpand = !result.isExpand
}
return result
})
self.currentList = output
self.tableView.reloadSections(IndexSet(integer: section), with: UITableView.RowAnimation.automatic)
self.tableView.endUpdates()
}
}

Tableview header cell expand with same cardView in swift?

I have attached the image click the card view expands the same card inside the table cell dynamically its passible to achieve this?
I have searched a lot but not working
Hear my code added header cell with CardView
added arrow button to click the button expand the cell
its able expand but not in parent card it was showing diff card
I have adde my source code
var hiddenSections = Set<Int>()
let tableViewData = [
["1","2","3","4","5"],
["1","2","3","4","5"],
["1","2","3","4","5"],
]
override func viewDidLoad() {
super.viewDidLoad()
let CustomeHeaderNib = UINib(nibName: "CustomSectionHeader", bundle: Bundle.main)
historyTableView.register(CustomeHeaderNib, forHeaderFooterViewReuseIdentifier: "customSectionHeader")
}
func numberOfSections(in tableView: UITableView) -> Int {
return self.tableViewData.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.hiddenSections.contains(section) {
return 0
}
return self.tableViewData[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = self.tableViewData[indexPath.section][indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return view.frame.width/4
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = self.historyTableView.dequeueReusableHeaderFooterView(withIdentifier: "customSectionHeader") as! CustomSectionHeader
header.setupCornerRadious()
let sectionButton = header.expandBtn
sectionButton?.setTitle(String(section),
for: .normal)
sectionButton?.tag = section
sectionButton?.addTarget(self,action: #selector(self.hideSection(sender:)), for: .touchUpInside)
return header
}
#objc
private func hideSection(sender: UIButton) {
let section = sender.tag
func indexPathsForSection() -> [IndexPath] {
var indexPaths = [IndexPath]()
for row in 0..<self.tableViewData[section].count {
indexPaths.append(IndexPath(row: row,
section: section))
}
return indexPaths
}
if self.hiddenSections.contains(section) {
self.hiddenSections.remove(section)
self.historyTableView.insertRows(at: indexPathsForSection(),
with: .fade)
} else {
self.hiddenSections.insert(section)
self.historyTableView.deleteRows(at: indexPathsForSection(),
with: .fade)
}
}
With out sections also you can achieve this. To do this,
1.Return cell height as section height. If user clicks on the cell then return total content height to the particular cell.
2.You need to take an array, if user selects cell, add indexPath number in to array. If selects already expand cell remove it from array. In height for row at index check indexPath is in array or not.
This is one of the way. With sections also you can do that.
//MARK:- UITableView Related Methods
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrDict.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
// var cel = tblExpandedTest.dequeueReusableCellWithIdentifier("expCell", forIndexPath: indexPath) as! CDTableViewCell
var cel : CaseHearingTabTVC! = tableView.dequeueReusableCell(withIdentifier: "caseHearingTabCell") as! CaseHearingTabTVC
if(cel == nil)
{
cel = Bundle.main.loadNibNamed("caseHearingTabCell", owner: self, options: nil)?[0] as! CaseHearingTabTVC;
}
//cell?.backgroundColor = UIColor.white
cel.delegate = self
if indexPath != selctedIndexPath{
cel.subview_desc.isHidden = true
cel.subview_remarks.isHidden = true
cel.lblHearingTime.isHidden = true
}
else {
cel.subview_desc.isHidden = false
cel.subview_remarks.isHidden = false
cel.lblHearingTime.isHidden = false
}
return cel
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectIndex = true;
if(selectedInd == indexPath.row) {
selectedInd = -1
}
else{
let currentCell = tableView.cellForRow(at: indexPath)! as! CaseHearingTabTVC
cellUpdatedHeight = Float(currentCell.lblHearingTime.frame.origin.y + currentCell.lblHearingTime.frame.size.height) + 2;
selectedInd = -1
tblCaseHearing.reloadData()
selectedInd = indexPath.row
}
let previousPth = selctedIndexPath
if indexPath == selctedIndexPath{
selctedIndexPath = nil
}else{
selctedIndexPath = indexPath
}
var indexPaths : Array<IndexPath> = []
if let previous = previousPth{
indexPaths = [previous]
}
if let current = selctedIndexPath{
indexPaths = [current]
}
if indexPaths.count>0{
tblCaseHearing.reloadRows(at: indexPaths, with: UITableView.RowAnimation.automatic)
}
}
func tableView(_ tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowIndexPath indexPath:IndexPath) {
(cell as! CaseHearingTabTVC).watchFrameChanges()
}
func tableView(_ tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowIndexPath indexPath:IndexPath) {
(cell as! CaseHearingTabTVC).ignoreFrameChanges()
}
func tableView(_ TableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
if indexPath == selctedIndexPath{
return CGFloat(cellUpdatedHeight)
}else{
return CaseHearingTabTVC.defaultHeight
}
}
Best approach is to create two different cells for normal card and expanded card.
fileprivate var selectedIndex: Int?
func registerTableViewCells() {
tableView.register(UINib(nibName:Nib.CardCell , bundle: nil), forCellReuseIdentifier: "CardCell")
tableView.register(UINib(nibName:Nib.ExpandedCardCell , bundle: nil), forCellReuseIdentifier: "ExpandedCardCell")
}
override func viewDidLoad() {
super.viewDidLoad()
self.registerTableViewCells()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
guard let index = selectedIndex else {
return 115
}
if index == indexPath.row{
return 200
}
return 115
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let selected = selectedIndex, selected == indexPath.row{
let cell = tableView.dequeueReusableCell(withIdentifier: "ExpandedCardCell", for: indexPath) as! ExpandedCardCell
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "CardCell", for: indexPath) as! CardCell
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if selectedIndex == indexPath.row{
selectedIndex = nil
}
else{
selectedIndex = indexPath.row
}
UIView.performWithoutAnimation {
tableView.reloadData()
}
}

iOS: How to create Expandable TableView in Swift without using Third party libraries or pods

I have Implemented Tableview in swift, but I want to Make an Expandable TableView, please give me an idea.
This is the code for Tableview,
//MARK: - TableView Delegate and Datasource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return MenuNameArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MenuTableViewCell", for: indexPath) as! MenuTableViewCell
cell.menuNameLabel.text = NameArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
Here You Go , Try This Out : -
struct ExpandableNames {
var isExpanded : Bool
var names : [String]
}
struct Contact {
let names : String
}
in your Class - >
var twoDArray = [
ExpandableNames(isExpanded : true,names:["Krishna","Rishabh","Aditya","Chandan","Nipun","Navdeesh","Steve"].map
{
Contact(names: $0)
}),
ExpandableNames(isExpanded : true,names:["Carl","Michal","Tommy","Jennny","Vikram","Swati"].map
{
Contact(names: $0)
}),
ExpandableNames(isExpanded : true,names:["David","dude","dfff","dcc","daa","dee","dsss"].map
{
Contact(names: $0)
}),
ExpandableNames(isExpanded : true,names:[Contact(names: "Pattrick", hasFav: false)])
]
let cellId = "cellID"
let identifier = "attachmentCellID"
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
{
return 50
}
func numberOfSections(in tableView: UITableView) -> Int
{
return twoDArray.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if !twoDArray[section].isExpanded
{
return 0
}
return twoDArray[section].names.count
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let btn = UIButton(type: .system)
if(section == 0)
{
btn.setTitle("Tap To View Classes", for: .normal)
}
else if(section == 1)
{
btn.setTitle("Tap To View Admins", for: .normal)
}
btn.setTitleColor(.black, for: .normal)
btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
btn.addTarget(self, action: #selector(handleExpandClose), for: .touchUpInside)
btn.backgroundColor = AppColors.greyBorderColor
btn.tag = section
return btn
}
#objc func handleExpandClose(button : UIButton)
{
let section = button.tag
var indexPaths = [IndexPath]()
for row in twoDArray[section].names.indices
{
let indexPath = IndexPath(row: row, section: section)
indexPaths.append(indexPath)
}
let isExpanded = twoDArray[section].isExpanded
twoDArray[section].isExpanded = !isExpanded
button.setTitle(isExpanded ? "Tap To View Classes" : "Classes", for: .normal)
if isExpanded
{
tableView.deleteRows(at: indexPaths, with: .fade)
}
else
{
tableView.insertRows(at: indexPaths, with: .fade)
}
}
And Rest in cellForRowAt -
let contact = twoDArray[indexPath.section].names[indexPath.row]
cell.textLabel?.text = contact.names
First you will need a model defining if the cell is open, for example, an array of indexPaths:
var openPaths = [IndexPath]()
now when select the cell you toggle wether it is open or not and reload the cell
if let index = openPaths.index(indexPath) {
openPaths.remove(atIndex: index)
} else {
openPaths.append(indexPath)
}
tableView.beginUpdates()
tableView.reloadRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
Now in your cell setup, use a stackview, and in the cell config, you hide the expandable part based on if the cells indexPath is in openPaths
Use heightForRowAt delegate method to change height of cell:-
Add a boolean property to your object say isExpanded, change the value in
didSelectRowAt delegate by
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
YourModel[indexPath.row].isExpanded = !YourModel[indexPath.row].isExpanded
tableView.reloadRows(at: [indexPath], with: Animation)
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if YourModel[indexPath.row].isExpanded {
return 200
} else {
return 50
}
}

ios 11 UITableViewHeaderFooterView not properly scroll in animation

I have collapse and expand animation in UITableView. Tableview has two section in which first section data is collapse and expand. This thing perfectly working with ios 10 but in ios 11 Section view repeated or overlapped with cell data which is expanded.
Below is my code
//MARK: -Table View delegate Method
func numberOfSections(in tableView: UITableView) -> Int {
return read_Localizable("titleHelpSection").components(separatedBy: ",").count
}
//MARK: -Table View Datasource Method
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat{
return 44.0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "headerView")
let arrSection = read_Localizable("titleHelpSection").components(separatedBy: ",")
if headerView == nil
{
headerView = UITableViewHeaderFooterView(reuseIdentifier: "headerView")
headerView?.contentView.backgroundColor = UIColor.white
let lblResult = UILabel()
lblResult.tag = 123456
lblResult.font = AppCommonSNMediumFont()
lblResult.textColor = UIColor.black
lblResult.translatesAutoresizingMaskIntoConstraints = false
headerView?.contentView.addSubview(lblResult)
let seperator = UIView()
seperator.translatesAutoresizingMaskIntoConstraints = false
seperator.backgroundColor = UIColor.black
headerView?.contentView.addSubview(seperator)
headerView?.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[seperator]|", options: [], metrics: nil, views: ["seperator":seperator]))
headerView?.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[lable]-(>=8)-|", options: [], metrics: nil, views: ["lable":lblResult]))
headerView?.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[lable]-[seperator(1)]|", options: [], metrics: nil, views: ["lable":lblResult,"seperator":seperator]))
}
if let lblResult = headerView?.contentView.viewWithTag(123456) as? UILabel
{
lblResult.text = arrSection[section]
}
return headerView
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 20.0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0
{
return (arrHelpData.count)
}
else
{
return 1
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0
{
var cell = tableView.dequeueReusableCell(withIdentifier: "HelpCell") as? CellHelp;
if cell == nil {
cell = CellHelp(style: .default, reuseIdentifier: "HelpCell")
cell?.selectionStyle = .none
cell?.txtContain.delegate = self
}
if let objModel = arrHelpData.object(at: indexPath.row) as? HelpModel
{
cell?.lblTitle.text = objModel.helpTitle
if objModel.isExpanded == true
{
cell?.txtContain.text = objModel.helpDesc
}
else
{
cell?.txtContain.text = ""
}
cell?.imgArrow.isHighlighted = !objModel.isExpanded
}
return cell!
}
else
{
var cell = tableView.dequeueReusableCell(withIdentifier: "DefultCell")
if cell == nil
{
cell = UITableViewCell(style: .default, reuseIdentifier: "DefultCell")
cell?.textLabel?.textColor = color1F87A3()
cell?.textLabel?.font = AppCommonSNRegularFont()
cell?.selectionStyle = .none
cell?.textLabel?.numberOfLines = 0
}
cell?.textLabel?.text = read_Localizable("titleSettings")
return cell!
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 0 && indexPath.row < (arrHelpData.count)
{
if let objModel = arrHelpData.object(at: indexPath.row) as? HelpModel
{
if objModel.isExpanded == true
{
objModel.isExpanded = false
}
else
{
objModel.isExpanded = true
}
tableView.reloadData()
}
}
}
Actual view
Section overlapped on cell data
This is very frustrating iOS11 issue, something to do around estimatedHeight issue, If you really want to keep the self sized row and header then u need to go with the below approach.
Declare variable which holds the height of the cell/header and store height into that and used it as below:
var cellHeightDictionary: NSMutableDictionary // To overcome the issue of iOS11.2
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 125
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cellHeightDictionary.setObject(cell.frame.size.height, forKey: indexPath as NSCopying)
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if cellHeightDictionary.object(forKey: indexPath) != nil {
let height = cellHeightDictionary.object(forKey: indexPath) as! CGFloat
return height
}
return UITableViewAutomaticDimension
}
This is the only solution which worked for me for iOS11 issues with auto sizing cells. Otherwise people suggest to keep estimatedHeight 0 to get rid off such issues.
In your case first try doing this for cell and that doesn't solve the issue completely then do same for header height also. Hope this helps!
Don't forget to test in both iOS11.1 and iOS11.2.

Adding two Custom cells in tableView

I have a tableView on mainStoryboard with two custom cells.
I would like to set two more cells at different row.
However When I implemented the code the added cells replaces original cells. (Custom cell of "Basic grammar3" and "Basic grammar5" are disappearing.)
I was trying to find the answer but could not find out.
I have image and code added below.
import UIKit
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tblStoryList: UITableView!
var array = PLIST.shared.mainArray
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.array.count + 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 || indexPath.row == 3 || indexPath.row == 5 {
let cell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell", for: indexPath) as! HeaderCell
cell.headerTitle.text = indexPath.row == 0 ? "First Stage" : indexPath.row == 3 ? "Second Stage" : "Third Stage"
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "StoryTableviewCell", for: indexPath) as! StoryTableviewCell
//making plist file
let dict = self.array[indexPath.row - 1]
let title = dict["title"] as! String
let imageName = dict["image"] as! String
let temp = dict["phrases"] as! [String:Any]
let arr = temp["array"] as! [[String:Any]]
let detail = "progress \(arr.count)/\(arr.count)"
//property to plist file を぀ăȘぐ
cell.imgIcon.image = UIImage.init(named: imageName)
cell.lblTitle.text = title
cell.lblSubtitle.text = detail
cell.selectionStyle = UITableViewCellSelectionStyle.none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
return
}
tableView.deselectRow(at: indexPath as IndexPath, animated:true)
if indexPath.row == 3 {
return
}
tableView.deselectRow(at: indexPath as IndexPath, animated:true)
if indexPath.row == 5 {
return
}
tableView.deselectRow(at: indexPath as IndexPath, animated:true)
let messagesVc = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
messagesVc.object = self.array[indexPath.row - 1]
self.navigationController?.show(messagesVc, sender: self)
}
You could use sections for your table view. Now, you are returning 1 in your numberOfSections function. And it is creating only one section. If you want to use headers, you can use sections for your need. And also you can fill your table view cells with multidimendional arrays. For example:
For adjusting your section headers:
let lessonTitles = ["First Stage", "Second Stage"]
Titles for sections:
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section < lessonTitles.count {
return lessonTitles [section]
}
return nil
}
For adjusting your sections and rows:
let lessons = [["Basic Grammar 1", "Basic Grammar 2"], ["Basic Grammar 3", "Basic Grammar 4"]]
Number of sections function should be:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return lessons.count
}
Number of rows in section should be:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return lessons[section].count
}
And creating your cells is like this:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellText = data[indexPath.section][indexPath.row]
...
}
Try like this...
func numberOfSections(in tableView: UITableView) -> Int
{
return numberOfStages
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return numberOfRowsInCurrentStage
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
return customizedCell
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat
{
return requiredHeight
}
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView?
{
return stageCountView
}
You can use viewForHeaderInSection if you want to show stage count on top.
edit: The comment by raki is the much better solution (use headers). I leave this here in case you want something closer to your existing implementation.
You have to change your numbering scheme in order to insert these additional rows (and not replace existing rows). So you might want to adjust the row for the "normal" elements like this:
func adjustRow(_ row: Int) -> Int {
if row < 3 {
return row
} else if row < 5 {
return row+1
} else {
return row+2
}
}

Resources