Expand/Collapse table row when multiple number of sections in tableview - ios

Here i am trying to create expand/collapse table row.it is working fine with this code in didSelectRowAtIndexPath only for 1 section:
if (selectedIndex == indexPath.row) {
selectedIndex = -1;
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil]withRowAnimation:UITableViewRowAnimationFade];
return;
}
//for table view collapse
if (selectedIndex != -1) {
NSIndexPath *prePath = [NSIndexPath indexPathForRow:selectedIndex inSection:0];
selectedIndex = (int)indexPath.row;
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:prePath, nil]withRowAnimation:UITableViewRowAnimationFade];
}
//for non selection
selectedIndex = (int)indexPath.row;
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil]withRowAnimation:UITableViewRowAnimationFade];
through this code i can expand and collapse table row but if and only if for 1 section in table but when multiple section comes it is expanding each sections particular row.so when i click on section 0's 1st row it is going to open all section's 1st row.
How to get rid of this situation?

Tapping on particular section button you can change number of rows.
In section view you have added one button for all section which has common method while tapping.
In tapping method you have to just change bool variable value for particular section
ex.. if sender tag you initials with section number.
So For Section 0 button is taped then in tapping method
if sender.tag == 0
{
if section0tag
{
section0tag = false
}
else
{
section0tag = true
}
table.reload() ..//Which call number of rows at section data source method
}
For number of rowsatSection method data source method
if section == 0
{
if section0tag
{
return 5 //Expanding rows
}
else
{
return 0 //collapsing rows
}
}

Try this method just reload tableview (i.e rOne,rTwo, etc are the bool value):
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 0) {
return rOne ? oneRoundType.count : 0 ;
}else if (section ==1) {
return rTwo ? twoRoundType.count : 0 ;
}else if (section ==2) {
return rThree ? threeRoundType.count : 0 ;
}else if (section ==3) {
return rFour ? fourRoundType.count : 0 ;
}else if (section ==4) {
return rFive ? fiveRoundType.count : 0 ;
}
return 0;
}

Please try below code:
Global declaration of sectionIndexToBeExpanded as int to check whether it is expanded or not
int sectionIndexToBeExpanded;
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//Assign value 100 to sectionIndexToBeExpanded, if you do not want row expanded
sectionIndexToBeExpanded = 100;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [yourArray count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (sectionIndexToBeExpanded==100) //If not expanded
{
return 1;
}
else if (sectionIndexToBeExpanded==section) //If section expand add one more row
{
return 2;
}
else
return 1;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row==0)
{
if (sectionIndexToBeExpanded==100) //If section not expanded set value of sectionIndexToBeExpanded to 100
{
UITableViewCell *cell=(UITableViewCell*)[tableView cellForRowAtIndexPath:indexPath];
[tableView beginUpdates];
[tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section]] withRowAnimation:UITableViewRowAnimationRight];
sectionIndexToBeExpanded=(int)indexPath.section;
[tableView endUpdates];
}
else if (sectionIndexToBeExpanded==indexPath.section) // If Section is already expanded at indexpath then collapse ie. delete row
{
UITableViewCell *cell=(UITableViewCell*)[tableView cellForRowAtIndexPath:indexPath];
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexPath.row+1 inSection:sectionIndexToBeExpanded]] withRowAnimation:UITableViewRowAnimationLeft];
sectionIndexToBeExpanded=100; //Set section to not expanded
[tableView endUpdates];
}
else //Expand section
{
UITableViewCell *cell=(UITableViewCell*)[tableView cellForRowAtIndexPath:indexPath];
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexPath.row+1 inSection:sectionIndexToBeExpanded]] withRowAnimation:UITableViewRowAnimationLeft];
//set value of expanded section to sectionIndexToBeExpanded
sectionIndexToBeExpanded=(int)indexPath.section;
[tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section]] withRowAnimation:UITableViewRowAnimationLeft];
[tableView endUpdates];
}
}
}
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 44;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}

Related

Expanding a table cell on clicking a button outside it in objective c

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView beginUpdates]; // tell the table you're about to start making changes
if ([indexPath compare:self.expandedIndexPath] == NSOrderedSame) {
self.expandedIndexPath = nil;
} else {
self.expandedIndexPath = indexPath;
}
[tableView endUpdates]; // tell the table you're done making your changes
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([indexPath compare:self.expandedIndexPath] == NSOrderedSame) {
return 200.0; // Expanded height
}
return 44.0; // Normal height
}
- (void)pieChart:(XYPieChart *)pieChart didSelectSliceAtIndex:(NSUInteger)index
{
This is a function of getting the index , when clicking a pie chart.
what i need to do is expand the corresponding row of table when pie is selected
}
#end
If i got your idea you need to select the row at index path
- (void)pieChart:(XYPieChart *)pieChart didSelectSliceAtIndex:(NSUInteger)index
{
// get indexPath with index
// remember if you have few sections then you will need to update inSection:0 value
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
[yourTableView selectRowAtIndexPath:indexPath
animated:NO
scrollPosition:UITableViewScrollPositionNone];
// This will also Highlighted the row. Then delegate
[yourTableView.delegate someTableView didSelectRowAtIndexPath:indexPath];
}

How to collapse my cell properly?

while i click the first cell its working properly and hiding correctly.
while i click second cell,The backend cell has been merged and displaying improperly.
whats wrong in this code please find out what is wrong in this code.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 2;
}
#pragma mark table cell creating and loading the data
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *returncell;
AntzclubCell *cell;
WaterPurifierCell *cell1;
if(indexPath.row==0)
{
cell=[tableView dequeueReusableCellWithIdentifier:#"Antz"];
cell.img_antzClub.image=[UIImage imageNamed:#"car.png"];
cell.lbl_antzClub.text=#"CAR";
cell.accessoryType=UITableViewCellAccessoryDetailDisclosureButton;
cell.backgroundColor=[UIColor blackColor];
return cell;
}
else if (indexPath.row==1)
{
cell1=[tableView dequeueReusableCellWithIdentifier:#"WaterPurifier"];
cell1.img_waterPurifier.image=[UIImage imageNamed:#"water_purifier.png"];
cell1.lbl_waterPurifier.text=#"WATERPURIFIER";
return cell1;
}
return returncell;
}
#pragma mark expanding height
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.row) {
case 0:
if(indexPath.row==selectindex)
{
return 350;
}
else
{
return 132;
}
break;
case 1:
if(indexPath.row==selectindex)
{
return 333;
}
else{
return 132;
}
default:
break;
}
return 0;
}
#pragma mark user selecting option
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%d %d",selectindex,indexPath.row);
if (indexPath.row==selectindex) {
NSLog(#"%d",selectindex);
selectindex=-1;
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
return;
}
if(selectindex !=-1)
{
NSIndexPath *prepath=[NSIndexPath indexPathForRow:selectindex inSection:0];
selectindex=indexPath.row;
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:prepath] withRowAnimation:UITableViewRowAnimationFade];
return;
}
selectindex=indexPath.row;
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
If you are trying to hide portions of the cell's content by shrinking its height, you'll need to check that the cell is set up to clip to its bounds (by default this is set to NO).
Select your prototype cell in the storyboard, and tick the "Clip Subviews" checkbox - the cell should then clip its contents when you shrink the height.

IOS inserting a row into UITableView

So I have a deadline coming up for this project and I've been working hard on it and so I'm pretty tired right now. I don't know if I'm just being stupid and blind to what I'm doing wrong but I have a problem that I need help with.
So, I'm trying to implement a sort of "expanding tableview setup" (like in IOS 7 calendar where you tap on the start and end dates and a cell pops in with a date picker). I have two different cells that can be displayed under a tapped cell. It works perfectly except for the actual cell, when I insert a row the wrong cell is displayed. I'll give some context... I have two cells in section 0, when you tap on the first cell it inserts a cell below it that should be a picker cell. Instead it inserts the same call as in row 1 of the unmodified tableview.
Here is the relevant code:
#interface AddMealTableViewController ()
#property (nonatomic) BOOL datePickerEnabled;
#property (nonatomic) BOOL pickerEnabled;
#property (nonatomic, strong) NSIndexPath *datePickerIndexPath;
#property (nonatomic, strong) NSIndexPath *pickerIndexPath;
#end
#implementation AddMealTableViewController
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
switch (section) {
case 0:
return 2 + (self.datePickerEnabled) + (self.pickerEnabled);
break;
default:
return self.mealComponents.count;
break;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.section) {
case 0:
{
if (indexPath.row == 1) {
TimeCell *cell = [tableView dequeueReusableCellWithIdentifier:#"TimeCell"];
cell.timeLabel.text = #"Now";
cell.mealTypeLabel.text = self.selectedMealType;
return cell;
}
else if (indexPath == self.datePickerIndexPath) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DateCell"];
return cell;
}
else if (indexPath == self.pickerIndexPath) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"PickerCell"];
return cell;
}
else {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MealTypeCell"];
cell.textLabel.text = #"Meal Type";
cell.detailTextLabel.text = self.selectedMealType;
return cell;
}
break;
}
default:
{
ComponentCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ComponentCell"];
if (!cell) {
cell = [ComponentCell new];
}
MealComponent *mc = self.mealComponents[indexPath.row];
[cell setUpWithComponent:mc];
return cell;
break;
}
}
return nil;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) {
if (indexPath == self.datePickerIndexPath || indexPath == self.pickerIndexPath) {
return 200;
}
return self.tableView.rowHeight;
}
return 70;
}
- (void)toggleDatePickerForSelectedIndexPath:(NSIndexPath *)indexPath
{
[self.tableView beginUpdates];
NSArray *indexPaths = #[[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0]];
if (self.datePickerEnabled)
{
self.datePickerEnabled = NO;
self.datePickerIndexPath = nil;
[self.tableView deleteRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
else
{
self.datePickerIndexPath = indexPaths.lastObject;
self.datePickerEnabled = YES;
[self.tableView insertRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
[self.tableView endUpdates];
}
- (void)togglePickerForSelectedIndexPath:(NSIndexPath *)indexPath
{
[self.tableView beginUpdates];
NSArray *indexPaths = #[[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0]];
if (self.pickerEnabled)
{
self.pickerEnabled = NO;
self.pickerIndexPath = nil;
[self.tableView deleteRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
else
{
self.pickerIndexPath = indexPaths.lastObject;
self.pickerEnabled = YES;
[self.tableView insertRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
[self.tableView endUpdates];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if ([cell.reuseIdentifier isEqual: #"TimeCell"]) {
[self toggleDatePickerForSelectedIndexPath:indexPath];
}
else if ([cell.reuseIdentifier isEqual: #"MealTypeCell"]) {
[self togglePickerForSelectedIndexPath:indexPath];
}
}
}
Any ideas? I really can't seem to put my finger on it.
why don't you change the height of date picker cell from 0 to 200 instead insert (or delete) the date picker cell. I think this is more simple.(This is what I'm used to implement that)
when [tableView didSelectRowAtIndexPath:] is called, you just call [tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic] to update cell.
You can managed the height of cell in [tableView heightForRowAtIndexPath:] you already know.
[edited]
I examine your code again.
change else if (indexPath == self.datePickefIndexPath) to else if([indexPath isEqual:self.datePickerIndexPath]) in [tableView:cellForRowAtIndexPath:]
There're many ways to handle this kind of things. You really don't need to insert or delete cell, just modify the cell height from 0 to the proper height. To do this, you can set a flag to check whether the cell's expanded or not.

Deleting rows from a static UITableView at runtime

Is it possible to delete rows from a UITableView at runtime when all of the sections and rows are defined statically in a nib?
In the following storyboard scene, can I delete the "Addr 2" field at runtime? In this case I have not provided a data source to the UITableView.
I don't know about "delete" but you can hide the row using tableView:heightForRowAtIndexPath:.
- (void)methodToToggleAddr2CellVisibility
{
self.addr2CellIsHidden = !self.addr2CellIsHidden;
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1 && indexPath.row == 1) { // the cell you want to hide
if (self.addr2CellIsHidden == YES) {
return 0;
} else {
return 44;
}
}
return 44;
}

Add and delete rows dynamically in multiple sections

I have searched and search and i just canĀ“t seem to find an answer to my problem. I have a dynamic tableview with 3 rows (each row is a section) and a edit button at the top right of the tableview. each time the user taps edit it has to be possible to add or delete a row. Everything works except the part when the + button is taped to ad a new row. This is my code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int count = [myarray count];
if (myarray != nil) count ++;
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
id cell;
switch(indexPath.section) {
case 0:
if(indexPath.row==0) {
static NSString *cellType1 = #"cellType1";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellType1];
return cell;
}
break;
case 1:
if(indexPath.row==0) {
static NSString *cellType2= #"cellType2";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellType2];
return cell;
}
break;
case 2:
if(indexPath.row==0) {
static NSString *cellType3= #"cellType3";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellType3];
return cell;
}
break;
default:
break;
}
return cell;
}
- (IBAction) EditTable:(id)sender
{
if(self.editing)
{
[super setEditing:NO animated:NO];
[Table setEditing:NO animated:NO];
[Table reloadData];
[self.navigationItem.rightBarButtonItem setTitle:#"Edit"];
[self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStylePlain];
}
else
{
[super setEditing:YES animated:YES];
[Table setEditing:YES animated:YES];
[Table reloadData];
[self.navigationItem.rightBarButtonItem setTitle:#"Ok"];
[self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStyleDone];
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.editing == NO || !indexPath) return UITableViewCellEditingStyleNone;
if (self.editing && indexPath.row == ([myarray count]))
{
return UITableViewCellEditingStyleInsert;
} else
{
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleNone;
}
- (void)tableView:(UITableView *)TableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[myarray removeObjectAtIndex:indexPath.row];
[Table reloadData];
} else if (editingStyle == UITableViewCellEditingStyleInsert)
{
switch(indexPath.section) {
case 0:
if(indexPath.row==0) {
static NSString *cellType1 = #"cellType1";
UITableViewCell *cell = [TableView dequeueReusableCellWithIdentifier:cellType1];
[arry insertObject:cell atIndex:[myarray count]];
[Table reloadData];
}
break;
case 1:
if(indexPath.row==0) {
static NSString *cellType2= #"cellType2";
UITableViewCell *cell = [TableView dequeueReusableCellWithIdentifier:cellType2];
[arry insertObject:cell atIndex:[myarray count]];
}
break;
case 2:
if(indexPath.row==0) {
static NSString *cellType3= #"cellType3";
UITableViewCell *cell = [TableView dequeueReusableCellWithIdentifier:cellType3];
[arry insertObject:cell atIndex:[myarray count]];
}
break;
default:
break;
}
}
As i said before, everything works until i press the + button (that appears on the left side when the edit button is pressed) to add a new row. Then it shows an error: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath.
What am i doing wrong? any help would be most appreciated.
First off, you never actually +alloc or -init a cell, so -cellForRowAtIndexPath: is most likely returning nil (-dequeueReusableCellWithIdentifier: doesn't cut it).
Second off, comparing indexPath.row to [myarray count] will never be true, because arrays and tables may be zero-based, but their counts aren't.

Resources