how to create expand and collapse tableview? - ios

I am able to expand and collapse the tableView sections successfully however I am not able to do it for individual sections so far.So all the sections collapse or expand at the same time.

You can collapse and expand tableView section by removing and adding tableViewCells on demand, like if you want to collapse reload that tableViewSection data and return zero in numberOfRowsInSection, and when you want to expand it back just return right amount of rows from numberOfRowsInSection method, it should be something like below
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//Check if section is collapsed
if (section_is_collapsed) return 0;
return actual_num_of_rows_in_Section;
}

Related

How to reload UITableView section with different row count?

This is a simple idea, but I can't seem to figure out the right solution.
I have a UITableView with many sections, including a header view.
I would like to be able to hide/remove each of the tableview cells in the sections I have, and then reload them back in with a nice animation.
My problem is that the number of sections could be different than before, and the number of rows in the sections could be different than before...
I can't simply fade out the entire tableview, and then reload it, and fade it back in because I need the header view to always be visible and scroll with the tableview.
I need to have them removed because the hiding and showing will be a nice "fade" animation with an activity indicator.
Just use the tableView methods
[self.tableView insertSections:(nonnull NSIndexSet *) withRowAnimation:(UITableViewRowAnimation)]
[self.tableView insertRowsAtIndexPaths:(nonnull NSArray<NSIndexPath *> *) withRowAnimation:(UITableViewRowAnimation)]
They will allow you to animate the insertion of new rows / sections. For Deletion there are similar methods, except they are called "deleteSections..." and "deleteRowsAtIndexPaths...".
Just take care that after insertion / deletion, these tableView's delegate functions return the current values:
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { }
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {}
And "correct" means: Amount of sections / rows before the insertion / deletion, plus or minus the amount of rows and sections after the insertion / deletion.
You can use this:
self.tableView.reloadRows(at: [indexPath], with: .fade)
Here index path is the specific rows that you want to reload. If you are changing the number of rows, you have to change the number of items in the data source. Or you can change the value returned by numberOfRowsInSection
For chaining animations you could use
let pathsForNewCells = [indexPathOne, indexPathTwo, indexPathThree]
myTableView.beginUpdates()
myTableView.insertRows(at: pathsForNewCells, with: [UITableViewRowAnimation])
myTableView.endUpdates()
thus, according to the documentation the height will animate without reloading the cells.

Mixing storyboard prototype cells with auto populating data

I have an auto populating UITableView from a NSMutableArray. I need to add a static cell to the top of the table from a prototype I built in storyboard. What is the correct way of doing this?
When I just added the prototype to the storyboard editor, it started out by covering up the first cell. After reloading the data, it would eventually appear under the other cells.
To make "space" for it, I made the table "editable" with the following code -
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.editing ? wOutputArray.count + 1 : wOutputArray.count;
}
Now it doesn't cover any cells, but it seems as though it doesn't have a home. At initial view load it's at the top of the table, then after a few refreshes it eventually falls back to the bottom of the table.
EDIT:
I'm reading that you can't mix static cells with dynamic cells, and that the table should be split up into sections.
So here I changed-
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableViewB{
return 2;
}
&
- (NSInteger)tableView:(UITableView *)tableViewB numberOfRowsInSection:(NSInteger)section{
switch(section){
case 0:
return 1;
break;
case 1:
return wOutputArray.count;
break;
}
return 0;
}
But I'm not sure what to do next... Is this the right direction?
Technically, both types of cells that you want to use are prototype cells - they are just different types of cell.
If you just want a static cell at the top of the others then all you need to do is account for it in your table data source methods.
First let the tableview know that there will 1+(dynamic cells count) cells
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return wOutputArray.count + 1
}
Second, in cellForRowAtIndexPath return the appropriate cell, accounting for the fact that indexPath.row will be 1 more than the element of your array (because row 0 is the static cell)
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell
if (indexPath.row==0) {
cell=tableView.dequeueReuseableCellWithIdentifier("staticCell",forIndexPath:indexPath)
// Any other manipulation as required
}
else {
cell=tableView.dequeueReuseableCellWithIdentifier("dynamicCell",forIndexPath:indexPath)
cell.label.text=wOutputArray[indexPath.row-1]; // Or whatever property you want to use
}
return cell!
}

Change the height of a static UITableViewCell only possible by overriding heightForRowAtIndexPath?

I've looked through lots of examples of how to hide a static UITableViewCell by overridding heightForRowAtIndexPath, and while I've now got it working it just seems so cumbersome that I'd like to see if I'm doing something wrong.
I have a UITableViewController with a table view that has about 8 rows. This screen in my app shows a single object, so for example one row is description, one is an image, one holds a map view, etc. All of the rows are static.
In some cases, some of the objects that are shown don't have a map, so I want to hide the row that holds the mapview. Since it's a static row, I was thinking that by having an outlet property for that row (e.g. #property (weak, nonatomic) IBOutlet UITableViewCell *mapViewRow;), then I could somehow set that row's height to 0 or hide that row in viewDidLoad or viewWillAppear. However, it seems like the only way to do this is to override the heightForRowAtIndexPath method, which is kind of annoying because then I need to hardcode the index of the map row in my code, e.g.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 6 && self.displayItem.shouldHideMap) {
return 0;
}
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
Of course, not a big deal, but just the whole way of sizing static rows in a tableview seems like it defeats the point of setting them up in the storyboard in the first place.
EDIT - rationale behind my answer
To change the height of a row you must reload either the whole table or a subset containing that row. B/c it's a bit odd to have a row in the table w/ zero height, I prefer modifying your data source such that the row doesn't exist in the table.
There are a number of ways to do that. You could build an array from your displayItem where each row in the array corresponds to a row in the table w/ appropriate data. You would rebuild this array and then call [tableView reloadData]. My original answer would also eliminate the unwanted row by treating each data element as a section with 0 or 1 rows.
ORIGINAL ANSWER
Is your tableview a plain or grouped style? If it's a plain style, you could treat each row as a section with either 0 or 1 rows in it. In your tableView dataSource and delegate methods you would use the section index to identify the data within self.displayItem that you care about for that section.
Your code would be something like:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 8; // max number of possible rows in table
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = 1;
// set self.mapSectionIndex during initialization or hard code it
if (section == self.mapSectionIndex && self.displayItem.shouldHideMap) {
rows = 0;
}
return rows;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:indexPath
{
return 60.0f; // whatever you want the height to be
}
// also modify tableView:cellForRowAtIndexPath: and any other tableView delegate and dataSource methods appropriately
you can override heightForRowAtIndexPath and just write in it return UITableViewAutomaticDimension; this will make cell calculate the height automatically as UILabel height is >= . it worked for me.

UITableView cell separators index incorrect?

I am trying to implement a UITableView where the odd indexes are a 'separator'. The problem is, when I have one object in my dataSource and load the tableView, I see the first cell fine. However, when there are two objects in my dataSource and then load the tableView, I only see the one cell even though there should be two cells. I have tried to reloadData to cell if that would change anything and it did not.
If you need code to see, just let me know!
I suspect your problem is in tableView:numberOfRowsInSection:. Because you are inserting "spacer" cells before your table's data cells, the number of rows returned from that method needs to take into account the spacer cells also, so the correct number to return is twice the number of elements in your array.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.cellArray count] * 2;
}

Table view cell expandable iOS

I want a table view with only cels, and when you click on a cell it should expand and show more info of the clicked cell.
I've seen quite some topics on this, but the most of them are linking to Table View Animations and Gestures on the apple developer page. Which does it in a different way. They use header sections, but I want to use the cell which is expandable for layout reasons.
I already tried several things mainly with
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
return 110;
}
else {
return rowHeight;
}
When I Click on the cell, the cell is expanded but the info in that cell stays the same. Also the heigth of the cell when expanded should be related to the amount of text in the details.
Thnx!
You can achieve this through the use of custom cells. Create two custom cells, one for the normal row and other for the expanded row. When the user touches a particular cell, you can record it's indexPath and reload the tableView. While reloading you can change the height of this selected row using the code that you've just posted(increasing the height of only the selected cell). This would give an effect of expanding cell.

Resources