I have a UITableView which consist of Chapters and Subchapters. On selecting Chapters the respective Subchapter will expand in UITableView. When I click the last Chapter the subchapter is not visible in the screen. Have to scroll below automatically when the subchapters appear.
You can either use
[self.table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
Or use
CGPoint bottomOffset = CGPointMake(0, yourTableView.contentSize.height - yourTableView.frame.size.height);
[table setContentOffset:bottomOffset]
This will scroll the tableView to the bottom when a new cell will be inserted to your tableView
On didSelectRowAtIndexPath method you need something like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
[tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationNone];
CGRect sectionRect = [tableView rectForSection:indexPath.section];
[tableView scrollRectToVisible:sectionRect animated:YES];
...
}
Hope it helps.
Related
I have a UITableView with cells that expand/collapse when users tap on them, using:
-(void)tableView:(UITableView *)_tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
...
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
...
}
After the reloadRowsAtIndexPath is run, I have heightForRowAtIndexPath return a different height depending on whether the cell is collapsing or expanding:
-(CGFloat)tableView:(UITableView *)_tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// if expand
return 200;
// if collapse
return 49;
}
When I collapse a cell at the bottom of the table, the table shrinks, but it is brought down way too far, leaving a significant amount of whitespace at the top of the table. I've tried [tableView scrollToRowAtIndexPath:indexPath] after calling reloadRowsAtIndexPaths, which solves the problem, but that makes the table jumpy. It would go down too far leaving whitespace then jump back to the top. How can I shrink the table cell without making it scroll down too far?
After you change something that affects tableView height, you can use these code to update cell height without reloading the table:
[tableView beginUpdates];
[tableView endUpdates];
Maybe you can use a UIView animation in main thread to avoid this,such as:
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:0.3 animations:^{
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}];
});
Then try:
if (#available(iOS 11.0, *)) {
self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAutomatic;
}
I have a static tableview that shows a date picker when the appropriate cell is selected. The didSelectRowAtIndexPath triggers the show/hide of the date picker cell; however, it's not until the second selection that scrollToRow is executed and the picker cell is hidden.
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
[tableView beginUpdates];
if (cell == self.dateCell){
self.dateOpen = !self.isdateOpen;
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
[self.tableView reloadData];
[self.tableView endUpdates];
}
Any Ideas of where I've gone astray??
Thank You!!
EDIT: I forgot to add, it's the last row that's expanding with the date cell... I'm wondering how that would affect it. Although, I did just copy/paste a few cells to make it not the last row and it didn't help.
I would like to make something like expandable cells. Result I'm trying to achieve is:
Actually I have:
Here is my code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
DoctorCell *cell = self.prototypeCell;
DoctorModel *doctor = [self.fetchController objectAtIndexPath:frcIndexPath];
// depending on isActive property I add (or do not add) some content.
[cell cellForDoctor:doctor isActiveCell:[self.activeCellIndexPath isEqual:indexPath]];
[cell setNeedsUpdateConstraints];
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height + 1;
}
Here is my cell selection method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
NSIndexPath *oldIndexPath = self.activeCellIndexPath;
if ([indexPath isEqual:self.activeCellIndexPath]) {
self.activeCellIndexPath = nil;
oldIndexPath = nil;
} else {
self.activeCellIndexPath = indexPath;
}
[self.doctorTableView beginUpdates];
[self.doctorTableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, oldIndexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.doctorTableView endUpdates];
[self.doctorTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
As you can see, my animation looks weird (kind of moving to wrong position, jumps, etc). What I'm doing wrong? Or do I need to pick another approach for expanding cells?
You can use UITableViews animation automation like this:
Call [tableView beginUpdates];
Change the data source.
Insert or delete rows and sections, or reload them
This should cause new heights to be calculated, etc.
Make sure you use something appropriate for the withRowAnimation parameter of these methods
Call [tableView endUpdates];
Your animation should now perform as expected.
Maybe your problem is that you selected UITableViewRowAnimationNone for the row animation.
I want to copy a row to another section when a button in the row is tapped.i have done it.But only the text is getting copied.I also want to move the image which is in that row.
-(void)moveRowToAnotherSection:(id)sender{
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)button.superview;
NSMutableArray *tempArr = [[NSMutableArray alloc] init];
[[self tableView] beginUpdates];
[tempArr addObject:[NSIndexPath indexPathForRow:self.favouritesArray.count inSection:0]];
[self.favouritesArray insertObject:cell.textLabel.text atIndex:self.favouritesArray.count];
[[self tableView] insertRowsAtIndexPaths:(NSArray *)tempArr withRowAnimation:UITableViewRowAnimationFade];
[[self tableView] endUpdates];
}
There are three points I want to make:
1) You want to move the image when a particular row is tapped, right?
Then why dont you use Tableview delegate's method- didSelectRowAtIndexPath.
2) There is a method in UITableView that is used to move rows. Here is from the Apple Documentation:
- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath
Moves the row at a specified location to a destination location.
Here is the piece of code that moves the tapped row to section 0 row 0.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSIndexPath *path = [NSIndexPath indexPathForRow:0 inSection:0];
[tableView beginUpdates];
[tableView moveRowAtIndexPath:path toIndexPath:indexPath];
[tableView moveRowAtIndexPath:indexPath toIndexPath:path];
[tableView endUpdates];
}
3) The third point is the main one. UITableView by default provides a reordering control and if you want to reorder rows by dragging and not tapping, you can achieve this following these steps:
Step 1:
Set your tableview to editing mode. Normally this is done through an Edit Button.
[_yourTableView setEditing:YES animated:YES];
Step 2:
In - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
assign
cell.showsReorderControl = YES;
Step 3:
Implement UITableViewDataSource's method
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath{
// here you do all the reordering in your dataSource Array. Because dragging rows change the index of your row but the change should reflect in yopur array as well.
}
Thats it, you don't need to write any code under beginUpdates and endUpdates block. You just have to implement these three steps.
Read this to learn all about Reordering in TableView
Can someone tell me how to move a row in UITableView automatically when selected.
To be more clearer my tableview has a number of items. When the users selects a row that row has to be moved to the bottom most row in UITableView.
Any code snippets or pointers would be appreciated.
Thanks
Use a method from UITableViewDelegate protocol
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger index = indexPath.row;
NSUInteger lastIndex = tableDataArray.count - 1;
if (index == lastIndex) {
return;
}
id obj = [[tableDataArray objectAtIndex:index] retain];
[tableDataArray removeObjectAtIndex:index];
[tableDataArray addObject:obj];
[obj release];
//// without animation
[tableView reloadData];
//// with animation
// [tableView beginUpdates];
// [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationBottom];
// [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:lastIndex inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
// [tableView endUpdates];
}
You can use the table view delegate methods to perform this.
To obtain the selected row u can use
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
This will help you to get an idea on moving rows.
http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/TableView_iPhone/ManageReorderRow/ManageReorderRow.html
when the row is selected modify your datasouce ,may be your array and reload table view.
ie
in your
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
get you indexpath and remove that data from your datasource array and place that value in your last of your data source array and finally reload tableview using
[tableview reloadData];