Expandable table cell content overflowing from cell - swift

I have an expandable tableview in my project as part of my tableviewcontroller. The issue is that when the table is not expanded, the rest of the cell is displayed anyway, overlapping with the next cell. The method I used to create expandable tables is from this tutorial: https://dev.to/lawgimenez/implementing-the-expandable-cell-in-ios-uitableview-f7j
I think they changed some things because this code was written in an older version of xcode and swift.
I have tried changing some properties of the cells and the tableview but nothing has worked so far.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableViewData[indexPath.row].opened = !tableViewData[indexPath.row].opened
tableView.reloadData()
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if tableViewData[indexPath.row].opened == true {
return 99.5
}
else {
return 40.5
}
}
I expected the cell in the tableview to cut off the custom cell at the exact height of the cell in the tableview but instead the cell is small when not expanded but all of the custom cell is diaplayed and overflows from assigned area for the cell.

You should use
tableView.reloadRows(at: [indexPath], with: .automatic)
instead of
tableView.reloadData()
Another thing, you should use
if tableViewData[indexPath.row].opened {
}
instead of
if tableViewData[indexPath.row].opened == true {
}

Related

TableView DidSelectRowAt will change background colors of other cells when I scroll

I have a TableView sometimes with enough cells allowing me to scroll through the table. At the same time I have set my didSelectRow to switch the background color of the cell. It seems that after selecting a few then scrolling down I find that more cells have been selected out of my control.
Here is my didSelectRowAt:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
packSizesTableView.cellForRow(at: indexPath)?.backgroundColor = UIColor.yellow
packList[indexPath.row].picked = true
pickedRows.append(indexPath)
Is there another way I should be selecting my table cells other than changing the color if the indexPath.row?
You can set cell color in cellForRowAt method as below:-
If packList[indexPath.row].picked {
yourCell.backgroundColor = UIColor.yellow
} else {
yourCell.backgroundColor = UIColor.red
}
Short answer: You are seeing the colors change on the wrong cells because cells get reused, and you need to set the color to the correct option when a cell is reused.
In the tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) method you can check your packList array to see if the cell being dequeued needs to be selected or not and set the color there. This will handle cases where a new cell is being created as well as cells that are being reused.
if packList[indexPath.row].picked {
cell.backgroundColor = UIColor.selectedColor
} else {
cell.backgroundColor = UIColor.defaultColor
}
You have several options for handling selecting/deselecting, so here is one option. In tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) you can simply do:
packList[indexPath.row].picked = !packList[indexPath.row].picked
tableView.reloadRows(at: [indexPath], with: UITableView.RowAnimation.whateverYouWant)
You could also do just update your packList array (which is needed for cellForRow), and override the logic in your cell's func setSelected(_ selected: Bool, animated: Bool) method.

Xcode static cells with dynamic backgroundColor

Is there a possibility to set a dynamic backgroundColor with static cells in a UITableView?
For example the user pressed a button in a UITableView and then all cells in the same view change to a specific color.
I already figured out how to set a backgroundColor when the view shows up:
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.backgroundColor = UIColor.black
}
Now I want to achieve the same when the view has already loaded. Any suggestions?
You can access the currently visible cells (the ones that have passed over the willDisplay milestone) via the visibleCells property. You can iterate over this array and do whatever you need:
for cell in tableView.visibleCells {
cell.backgroundColor = UIColor.black
}
Alternatively you can call reloadData() on the tableView, this will result in all cells being re-created and re-displayed.
You can use a delegate method called DidSelect this method works when a user tap on a cell in the tableView or inside an element, and returns the index path of selected Cell you can use that to edit background color or anything.
The code should be something like this optional func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) inside this function you can get the cell using cellForRowAtIndexPath and pass it the selected path and cast it as the cell type you have and then edit it or do whatever.
The full code would look something like this
optional func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath){
let cell = tableView.cellForRow(at: indexPath)
//use the cell object and do what you want
}

Swift Changing the size of tableview cells

just like the title says I'm searching for a way to change the size of each cell in my tableview. I have 2 questions:
1) How can I change the size of all cells by the same amount in my tableview?
2) Is it possible to automatically adjust the size of the cell based on the length of the text in that particular cell?
I'm aware that there are already similar questions asked before but I couldn't manage to implement their answers correctly as they've been outdated for some time now. I'd appreciate any help, thank you in advance!
1) To change size of all cells with same type, first you need to create CellType, here is the explanation how to do this.
https://stackoverflow.com/a/51979506/8417137
or you can check for indexPath.row, but it's not cool :)
Than here:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch cellType {
case firstType:
return firstCellTypeHeight
case secondType:
return secondCellTypeHeight
default:
return defaultCellHeight
}
}
2) Yes, its possible. You create your CustomCell. In your CustomCell you should
setup your textFields or labels inside ContentView. Your views with text will stretch your cell.
Important thing. In method above you must return special height like that.
return UITableViewAutomaticDimension
For example your code will looks like that.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch cellType {
case firstType:
return firstCellTypeHeight
case secondType:
return secondCellTypeHeight
// Your stretching cell
case textCellType:
return UITableViewAutomaticDimension
}
}
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
switch cellType {
case firstType:
return firstCellTypeHeight
case secondType:
return secondCellTypeHeight
// Your stretching cell
case textCellType:
return UITableViewAutomaticDimension
}
}

Tableview creates five rows on one row?

I have a tableView with a custom cell that I have told should give me 5 cells in return of this custom cell. The question now is that I am running the app and getting five rows on one row. I have changed from default size of cell to custom but that is nearly the only thing I have done. So now I wonder what can create this kind of problem?
The code of my tableView looks like this.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "theoryCell") as! theoryTVC
return cell
}
So the problem is you are using custom cell with custom height but you are not setting height for row in table view method.
Try this:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 100.0 //Choose your custom row height
}

Dynamic cell size with resize cell animation

I have a table view with a dynamic height of cells. Above the table is menu with buttons. When I click on the menu button, the data is loaded into the table. When data is loaded, I want to have an animation in a cell that changes the height of a cell. I wonder how this can be done?
Thanks for the help.
Swift 4
Create a boolean variable in your model for checking if your cell is expanded or not.
if you want to expand the cell as long as your label height you should connect you labels constraint to your contentView in all directions and set number of lines to 0 in your storyboard.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
details[indexPath.row].cellIsOpen = !details[indexPath.row].cellIsOpen
detailTableView.reloadData()
detailTableView.beginUpdates()
detailTableView.endUpdates()
detailViewHeightConstraint.constant = CGFloat(detailTableView.contentSize.height) // the height of whole tableView
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if details[indexPath.row].cellIsOpen {
return UITableViewAutomaticDimension // or any number you wish
} else {
return 60 // default closed cell height
}
}
}
Also you can place this two lines in your viewDidLoad() function:
detailTableView.estimatedRowHeight = 60
detailTableView.rowHeight = UITableViewAutomaticDimension