I've implemented a UITableView that has section headers above each section. I've designed the table with the Grouped style so the headers scroll with the table instead of fixing to the top. I have also added a section index so users can tap/swipe to jump to a specific section. The problem is doing so jumps to that section but it shows the section header at the top. In this case that's undesirable - I want to scroll so the very top of the first cell is at the top of the screen, with that section header not visible.
How can you scroll just past the section header when the user taps an icon in the section index for UITableView?
Just try this
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 section:desiredSectionIndex];
[tableView scrollToRowAtIndexPath: indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
Found a solution. Perhaps there is a cleaner solution but this is working well for me.
Return -1 to prevent the table view from scrolling to any section when that method is called. Just before the return, add the logic to scroll to the desired location by getting and modifying the frame of the next cell.
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
CGRect nextRowRect = [tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:index]];
nextRowRect.origin.y -= tableView.rowHeight;
nextRowRect.size.height += tableView.frame.size.height - tableView.contentInset.top - tableView.contentInset.bottom - tableView.rowHeight;
[tableView scrollRectToVisible:nextRowRect animated:NO];
return -1; //prevent auto scroll
}
Related
I try to make cells expand/collapse with drop-down like animation, so when table view recalculates height it moves down other cells below the one that was tapped,
but if the tapped cell top margin is not entirely visible, table view changes its height update behavior by moving all above cells up:
http://imgur.com/CldzuFf
Is there a way to make cells expand with top-to-bottom behavior always?
Reloading cells like this:
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:arrayToReload withRowAnimation:UITableViewRowAnimationBottom];
[self.tableView endUpdates];
Just set the contentOffset based on selected row
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell * theCell = (UITableViewCell *)[tableView
cellForRowAtIndexPath:indexPath];
CGPoint tableViewCenter = [tableView contentOffset];
tableViewCenter.y += myTable.frame.size.height/2;
[tableView setContentOffset:CGPointMake(0,theCell.center.y-65) animated:YES]; // need to customize the y offset 65 to your value
// reload row here
}
Using the willDisplayCell method I got the index of the last visible cell:
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
indexVisibleCell = [indexPath indexAtPosition:[indexPath length] - 1];
}
where indexVisibleCell is an NSUInteger that is declared in the class' interface. My problem is that I want to shift only one cell when user taps on the right or left button. I have applied this code for that purpose:
- (IBAction)rightButton:(id)sender {
NSUInteger indexOfScrolledCell;
indexOfScrolledCell = indexVisibleCell;
if (indexVisibleCell < 9) {
NSIndexPath *path = [NSIndexPath indexPathForRow:indexOfScrolledCell+1 inSection:0];
[self.obj_CollectionView1 scrollToItemAtIndexPath:path atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
}
}
as I show 3 cells at a time. By using that rightButton action method it shifts 3 cells at a time, not one. Please help me figure out how to scroll one cell at time.
Try using UICollectionView with paging enabled. Use following code, hopefully it works out for you.
[yourCollectionView setPagingEnabled:YES];
Use visibleCells to get your visible Cells, get the leftmost Cell index to figure out the next index, then scroll to that Cell on the left (similar logic to your code).
willDisplayCell is not reliable since it is called both times when you scroll left/right, and you're thinking that index is the left/right most is not correct.
Edit:
Or you need to compare the index in willDisplayCell correctly, to get the correct left/right most index, based on your logic.
For right button you can use following
[self.obj_CollectionView1 scrollToItemAtIndexPath:path atScrollPosition:UICollectionViewScrollPositionRight animated:YES];
and for left button following
[self.obj_CollectionView1 scrollToItemAtIndexPath:path atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
I am changing UICollectionViewScrollPosition so that when you scroll to right new item shows up on right side of collection view and when you scroll to left new item shows on left side of collection view.
In my app I am trying to display Mkmapview in UITableView. When I tap the cell, it has to expand and show the map. Then if I tap another cell, it should act again expand and show gallery view , the previous cell must collapse and map should be hide.
thanks in advance,
You have to keep track of the state (or height) of the expanding/collapsing cell. Then report that height in tableView:heightForRowAtIndexPath:. Then add the code below to trigger the resizing.
[self.tableView beginUpdates];
[self.tableView endUpdates];
For example:
- (void)toggleMapCell {
_mapCellExpanded = !_mapCellExpanded;
if (_mapCellExpanded)
_mapCellHeight = 200.0;
else
_mapCellHeight = 44.0;
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath isEqualTo:_mapCellIndexPath])
return _mapCellHeight;
else
return 44.0;
}
If you have to re-layout the cell's content. I think the best place is to do it in the cell's layoutSubviews.
In my table view, I have three sections, of which the first section contains a image cell, the second section contains segment control cell, and the third section contains some label cells.
What I am doing is when the user scrolls up the table view, everything will scroll up but the position of the segment control cell will be fixed at the upper margin of the screen.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSIndexPath *indexPathOfCurrentHeaderCell = [NSIndexPath indexPathForRow:0 inSection:0] ;
UITableViewCell *headerCell = [self.tableView cellForRowAtIndexPath:indexPathOfCurrentHeaderCell];
if (headerCell.frame.origin.y < self.tableView.contentOffset.y)
{
self.cellHead.hidden = NO;
self.cellHead.frame = CGRectMake(0, self.tableView.contentOffset.y, self.cellHead.frame.size.width, self.cellHead.frame.size.height);
}
[self.tableView bringSubviewToFront:self.cellHead];
}
But the function bringSubviewToFront: does not seem to work here (the second section will be covered by the third section). I think it is because the cells are not the subviews of the table view.
What can I do if I want to pull the segment control cell to the front?
You should add the segment control as a header instead of a cell in the tableview, using
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
then, you would have 2 sections,
1. image cell
2. segment control as header, labels as the cells
I have a UITableView with custom cells in it. The cells expands when I tap on them. I am facing an issue when I tap on the cell which is half cut by the bottom screen edge of the device. When I tap on this cell, I want cell to move up and then expand to show the details but right now it just expands and I do not know if is expanded or not. I need to manually scroll the table view up to see it.
Below is my cell tapping code. I implemented the related cell expansion methods and cell is expanding properly.
- (void)cartTableView:(UITableView *)iTableView didSelectRowAtIndexPath:(NSIndexPath *)iIndexPath {
[self.temporaryCartTable scrollToRowAtIndexPath:iIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
[self expandOrCollapseCartCellAtIndex:iIndexPath];
}
- (void)expandOrCollapseCartCellAtIndex:(NSIndexPath *)iIndexPath {
self.selectedIndexPath = iIndexPath;
[self.temporaryCartTable beginUpdates];
[self.temporaryCartTable reloadRowsAtIndexPaths:#[iIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.temporaryCartTable endUpdates];
}
After expanding, call scrollToRowAtIndexPath, which should position your cell correctly.
You need to check if rect of the cell you're extending (rectForRowAtIndexPath:) is fully within the bounds of the table view (based on contentSize and contentOffset, using CGRectContainsRect and if it's not - and only partially visible - then you need to scroll it to the bottom/top of the table view.