Expand and collapse cells in tableview - ios

I have a tableview. Some cells contain images, other text.
I want to be able to collapse and expand the cells. In order to be able to do so I did the following:
I created a variable isExpanded = true
In cellForRowAt I check if the cell contains text and then...
if textIsExpanded {
cell.textLabel?.sizeToFit()
cell.textLabel?.numberOfLines = 0
}
so that the cell can be as tall as the text inside of it.
In the action I toggle textIsExpanded and reload the table:
textIsExpanded.toggle()
table.reloadData()
This procedure perfectly works with tableviews only containing text.
Something that would work was expanding the if statement and in the false branch calling:
cell.textLabel?.invalidateIntrinsicContentSize()
cell.textLabel?.layoutIfNeeded()
BUT this doesn't work when I toggle the variable, this only works on launch.
How can I collapse and expand back the cells in my tableview?

Create your cell with a stack of two views, Upper view and lower View, Add a Bool key to your Model isExpandable that is triggered and changed on didSelect and check on this to hide or show your view, EIther keep the text as text or TextView up to you.

Related

How to add unique insets to specific UITableViewCells?

I have a UITableView whose insetsContentViewsToSafeArea property is set to false - this makes the tableView span the width of the screen.
The amount and different types of cells are driven by the server, so there's no way of knowing the content of the tableView.
What I'd like to to:
Assign unique insets to certain cells only.
I can't post a screenshot, so I'll try to make a quick doodle:
These three cells are all in the same UITableView:
|[This is one cell that goes edge-to-edge]|
|[Here's another one]|
|-----This cell needs its own insets-----|
Question:
What's the best way to achieve this?
What I've tried:
Overriding layoutMarginsDidChange
Trying to add layoutMargins directly in cellForRowAtIndexPath...
Create a UITableViewCell subclass for the cell with custom insets.
Then you have 2 options --
Add a subview to cell's contentView with constraints -- these will correspond to your desired insets. This view will act as your " pseudo contentView" (add cell content to it)
Play around with contentView's insets. (not sure if it'll work)
I hope this will get you started.
You can use the cell subclass for all cell cases too if you want -- with an enum style which you can set in cell for row.
enum Style {
case edgeToEdge
case withInset(inset: UIEdgeInset)
}
inside cell subclass
var insetStyle: Style = .edgeToEdge {
didSet {
//update the constraints of the pseudo content view
}
}

How to hide a label within uitableview custom cell

I have a custom UiTableView with a few cells.
Each cell contains a few UILabels.
somtimes I want to hide a specific label, while keeping its position empty, to avoid other fields repositioning.
in android, I used the following code:
holder.layoutTemperature.setVisibility(View.INVISIBLE); // hide, but keep its place.
if (myFlag) {
holder.layoutTemperature.setVisibility(View.VISIBLE);
}
How do I do it in swift?
You can any View's visibility like this:
myLabel.isHidden = true
You need this inside cellForRowAt
cell.lbl.isHidden = true/false
To hide the label but keep its position , you simply set its ".isHidden" to "true".
For example,
let label = UILabel()
label.isHidden = true

Show entire table view inside cell

I need to display a dynamic table view inside a cell (of a static table). Using sections instead will not be enough for me. But I don't want this table to be scrollable, so the entire table must appear at once. The problem is that this table size [and rows count, and each row size] varies according to the content being shown. How can I associate the cell (which holds the table) autoresizing property with a table inside that must show all content at once?
Currently I have the tableView inside the cell, and constraints bonds it to all the 4 sides. The first table (not the one inside the cell) rowHeight property is set to UITableViewAutomaticDimension, but the table inside the cell doesn't appear entirely.
If I set the static cell height to a value greater than the tableView(inside cell) height, the whole table appears, and also an extra space beneath it (as the table is bounded to 4 sides of the cell)
So, any ideas on how to show this entire table inside a cell that dynamically has the perfect size for it ?
ps: I tried using collection view inside the cell. Unfortunately it doesn't serve my purpose.
Thanks!
Update
I tried to create a class for the inner table and use (as pointed by iamirzhan) contentSize didSet, like so:
override var contentSize:CGSize {
didSet {
self.invalidateIntrinsicContentSize()
}
}
I then used this method to call a function that resizes the cell that holds the table: self.frame.size.height = table.contentSize.height. The function is on this cell's own class.
This worked, the table now appears entirely. The problem is that it overlaps the cell underneath it, so i'm still looking for a solution.
I don't see why this requires 2 tableviews. The static portion should be uitableviewheaderfooters or just a UIStackView. But to answer your question simply query your child tableView for its size and return this in tableView:heightForRowAtIndexPath: for the outer tableview. The height of the child tableView is simply the sum of the hieght of all of its children (including any headers/footers). This is usually not difficult to calculate unless you are using something like a webview where you need to actually load the content and get the size asynchronously. You can calculate the size of elements that are based on their intrinsic content size with UIView.sizeThatFits(_:). The other elements should have fixed sizes or constants in the storyboard that you can sum up.
For inner tableView you should write such implementation.
Firstly, disable the scrollEnable flag
Then you should override the intrinsicContentSize method of tableView
Your inner tableView custom class:
class IntrinsicTableView: UITableView {
override var contentSize:CGSize {
didSet {
self.invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
self.layoutIfNeeded()
return self.contentSize
}
}
Now, delete the height constraint, and the height will be calculating by its content.

Swift Dynamically growing a cell depending on the text length

I have a TableViewController which contains 2 sections:
Section 1 - is a cell which is loaded from a xib file. This cell just contains a TextView.
Section 2 - Contains multiple cells populated from an Array.
The section 1 only exists if the master (previous) UITableView cell you select contains a certain piece of data.
All of the above works as expected, below is the parent view. The list of items come from a database, some items have a description, and some do not. For example below this image, you'll see the view is 'Classic Starters' is selected. Then below that, you'll see the view if 'Stir Frys' is selected. Stri Frys contains a description:
Now, what I want is, the description cell which is shows on the Stir Frys page, to automatically grow depending on the length of the text inside it. So if a description is 10 lines long, it will grow to show all 10 lines.
Does this have to be done programmatically, or is their a feature in XCode I'm missing ?
You can use UITableViewAutomaticDimension.
1)
Set properties estimatedRowHeight and rowHeight of your tableview, in viewDidLoad for example. Like this :
self.tableView.estimatedRowHeight = 50
self.tableView.rowHeight = UITableViewAutomaticDimension
2) Return UITableViewAutomaticDimension in your heightForRowAt delegate method :
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
First you need to do is to set estimatedRowSize to a value that best estimates most common size, and rowSize to UITableViewAutomaticDimension:
self.tableView.estimatedRowHeight = 44
self.tableView.rowHeight = UITableViewAutomaticDimension
In your case, since except the first one all the other cells are supposed to be the same, you can use the height of the rest of the cells as the estimatedRowHeight.
You don't have to implement heightForRowAt at all.
The second step you need to do is to setup proper constraints on the cells. That means you have to constrain the contents of the cell to the left, right, top and bottom of the cell, so that when contents grow, the cell will need to grow, too. Common mistake is to forget to constrain bottom, so then the cell does not grow and the contents leak through the bottom of the cell.
Third, since your dynamic cell contains UITextView, you need to make sure that it will grow with its text. That is not automatic. To achieve that, based on this answer, this should suffice (in the cell):
textView.isScrollEnabled = false
If you are using storyboard, just uncheck scroll enabled.

scrollup uitablviewcell partially visible

I need some help.
That i want to scrollup uitalbeview cell which is partially
displaying.See screen shot.
Here my tableview has a three section and u can see that in morning
section the row is displaying partially.I just want to move up that
kind of row.
I tried content offset but not getting any idea that how to get first
visible row offset so,i can calculate and move it up or down
.
Note: not for bottom row only top rows.
This is the default behavior of a UITableView. The section headers will stick at the top of the screen until the next section header will reach it. One easy work around is to not use headers at all and simply use two cells. You would then have to add code in your viewForCellAtIndexPath:
if(indexPath.row == 0) {
//setup a header cell
} else {
//setup a data cell
}

Resources