Expand static TableViewCell with UI Switch - uitableview

I have been searching for this answer and my problem seems to be two-fold: (1) answers are from 2011 and I'm too new to Swift to translate old code and (2) in implementing the code I have found, it changes the height of ALL the cells in the tableView. I have some cells that are larger than others and I need them to be left alone by this.
My question is how to target a single cell's height to expand and contract based on a switch being toggled and have it not effect the height of any other cells.
iOS "create new calendar" event is what I'm looking for and the expandable cell will have a date picker in it, if that matters. Also, I'm using STATIC cells...some being custom and some using built-in features.
EDIT -- added code
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 1 && indexPath.row == 2 {
pickerVisible = !pickerVisible
tableView.reloadData()
}
tableView.deselectRow(at: indexPath, animated: true)
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 1 && indexPath.row == 2 && toggle.isOn == false {
return 0.0
}
if indexPath.section == 1 && indexPath.row == 3 {
if toggle.isOn == false || pickerVisible == false {
return 0.0
}
return 165.0
}
return 44.0
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 44.0
}

Related

Xcode 13 update height UITableViewCell

tell me how you can fix this behavior in xcode 13, updating the cell height does not work. In xcode 12.5.1 works fine
https://www.icloud.com/iclouddrive/0Wq4Ml4Zl_0Hk4XcQxrQ3FIwg#TableView
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if isHideCell && indexPath.row == 1 {
return 0
} else {
return tableView.rowHeight
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard indexPath.row == 0 else { return }
isHideCell = !isHideCell
tableView.performBatchUpdates(nil)
tableView.deselectRow(at: indexPath, animated: true)
}
This is not an issue with Xcode 13 -- it's an issue with iOS 15
Apparently (based on quick testing), heightForRowAt treats zero-height rows as "non-visible rows" and so it is not called for that row if you've set it's height to Zero.
You can try to get around this by setting the row height to 0.01 instead:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if isHideCell && indexPath.row == 1 {
return 0.01
}
return tableView.rowHeight
}

Correct way to delete item uitableview swift 4

I have a UitableView with 3 section (3 cell), In section 1 I have a list of item where user can delete using button, all delete process is good but when I delete a item; the uitableview goes to top and goes to bottom (is something like reload the view) and I want that
When user delete a item only remove from position this is my code
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var value: Int = 0
if(section == 0){
value = 1
}else if(section == 1){
value = items.count //20
}else if(section == 2){
value = 1
}
return value
}
#objc func delete_item(sender: UIButton){
let point = sender.convert(CGPoint.zero, to: tv_items)
guard let indexPath = tv_items.indexPathForRow(at: point) else{
return
}
tv_items.beginUpdates()
self.items.remove(at: indexPath.row)
tv_items.deleteRows(at: [indexPath], with: .fade)
tv_items.endUpdates()
}
cell.btn_delete.tag = indexPath.row
cell.btn_delete.addTarget(self, action: #selector(delete_item), for: .touchUpInside)
Thanks in advance
Use the below method and I think it will solve your issue:-
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50.0 // height of the row (Eg. 50.0)
}
If you are using estimatedHeightForRowAt, disable this and use heightForRowAt function.
Alternatively, use this after endUpdates():
tv_items.scrollToRow(at: indexPath, at: .top, animated: false)
If you have a constant row height, you can use:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80 // or any constant height
}
If you need varying height based on content, lemme know what the content is so I can help.

Expandable cell won't expand

I have created two expandable cells but the second one doesn't expand when I tap on it
I googled a lot of ways how to do this but this one seemed the shortest and the simplest one.
private var dateCellExpanded: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// For removing the extra empty spaces of TableView below
self.tableView!.tableFooterView = UIView()
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
if dateCellExpanded {
dateCellExpanded = false
} else {
dateCellExpanded = true
}
tableView.beginUpdates()
tableView.endUpdates()
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 {
if dateCellExpanded {
return 250
} else {
return 40
}
}
return 40
}
I expect to be able to add as many cells as I want and have them expand on tap, but only the first one does.
Here's what happens
It's only working for the first row because you're limiting it to the first row with if indexPath.row == 0.
You'll need an array of Bool rather than a single Bool as you need to track the state for all rows.
Just initialize the array to an array of false values with the count of your rows. Set NUMBER_OF_ROWS below accordingly.
Then, when selecting a cell, you flip (or toggle()) the boolean for that row and ask the table to update.
private var isCellExpanded: [Bool] = Array(repeating: false, count: NUMBER_OF_ROWS)
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
isCellExpanded[indexPath.row].toggle()
tableView.beginUpdates()
tableView.endUpdates()
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if isCellExpanded[indexPath.row] {
return 250
} else {
return 40
}
}
Note that this assumes that you're only using one section. Otherwise you'll have to adjust the data structure [Bool] to [[Bool]].

Set height of a specific cell in my UITableView

I have two cells (one dynamic and other static) and I want to set different height for each cell like:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
/*tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath)
tableView.dequeueReusableCell(withIdentifier: "Cell2", for: indexPath)
if cell1 return 100
if cell2 return 20 */
}
It's possible to specific height for each cell not row.
How can I resolve this issue?
For static cell (created either as Xib or in storyboard), you can set the height like this, if you are displaying static cell in first row of your Table View.
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 0 {
return 120
}
return UITableViewAutomaticDimension
}
To populate the static cell along with dynamic cell, You should do,
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return datasource.count + 1
}
UITableViewAutomaticDimension
https://www.raywenderlich.com/129059/self-sizing-table-view-cells -
If you set correctly the autolayout for the cell you can use UITableViewAutomaticDimension to have the size without have to specify.
You only need to return a height for each indexPath. There is no need to dequeue a cell here. If you want different prototype cells you will do this in cellForRowAtIndexPath.
You can specify as many sections and rows as you want:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch indexPath.section {
case 0:
switch indexPath.row {
case 0:
return 100.0
case 1:
return 20.0
// Add rows here if needed
default:
return UITableViewAutomaticDimension
// Add sections here if needed
default:
default:
return UITableViewAutomaticDimension
}
}
*In, Swift 3.0
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 {
return 100
} else {
return 200
}
}
or you can set Constraint of your Cell proper and then write this code of your ViewDidLoad Method
yourTblView.estimatedRowHeight = 100
yourTblView.rowHeight = UITableViewAutomaticDimension*
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 {
return 100
} else {
return 20
}
}

Changing height of individual cell UITableView

I would like something like the following:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("NewsCell", forIndexPath: indexPath) as! UITableViewCell
if indexPath == 3{
cell.height = "50dp"
}
return cell
}
what is the alternative or the easiest way to go about this?
EDIT
Is it possible for me to also specify section number: i.e-
if sectionIndex == 5
I suggest use the heightForRowAtIndexPath function. TableView will call this function to determine the row height for a specific indexpath.
Sample code:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.section == SECTION_INDEX {
return 60
} else {
return UITableViewAutomaticDimension
}
}
Swift 4:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == SECTION_INDEX {
return 60
} else {
return UITableViewAutomaticDimension
}
}
A little explain:
indexPath have two properties: section and row. By checking these two properties, you can make your own control flow to determine the height for each cell.
If you return 60, it means you want the cell's height to be 60 points. If you return UITableViewAutomaticDimension, you want the system to decide the best height for you (in this case, you'd better set autolayout for the cell in storyboard).
I also suggest you take the stanford course CS193p on iTunes U, it would be of great help to you :)
the easiest way is to override heightForRowAtIndexPath
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let section = indexPath.section
let row = indexPath.row
if section == 0 && row == 2{
return 50.0
}
return 22.0
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat{
if indexPath.section == 5
{
if indexPath.row == 3
{
return 150.0
}
}
return 200.0
}
Following Zhu Shengqi's answer, here is the Swift 5+ code.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == SECTION_INDEX {
return 160
} else {
return UITableView.automaticDimension
}
}
the easiest way is to override heightForRowAtIndexPath delegate method is there in tableview.
These method based on content it will change the height automatically.
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableView.AutoDiemensions
}

Resources