Expand tableHeaderView as UITableView scrolls like Twitter - ios

I'm trying to expand UITableView's tableHeaderView like how Twitter does it (well more like how they used to do it). As I was messing with it, I happened to implement -scrollViewDidScroll like this:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (self.tableView.contentOffset.y < 0) {
float offsetY = self.tableView.contentOffset.y;
CGRect tblFrame = self.tableView.tableHeaderView.frame;
[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
self.tableView.tableHeaderView.frame = CGRectMake(tblFrame.origin.x, offsetY, tblFrame.size.width, originalHeaderHeight-offsetY);
}
}
and it works almost exactly how I wanted it to. I went back to clean it up, and I took the [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; out, and it stopped working.
When I take out -cellForRowAtIndexPath: tableHeaderView's y origin does not get changed, so it expands, but it does not stay at the top of the view. Can someone help me with this?

Related

Scroll UITableViewCell to visible not working as intended

I have a button in a UITableViewCell which is stored as an ivar called currentButton. When that button is clicked a UIView containing a UIPickerView and UIToolBar is invoked and shown from the bottom of the screen. However, I have looked at other posts for hours and this following code still doesn't work. The cells sometimes scroll down below the keyboard and the cells all the way at the bottom of the UITableView do not scroll up enough to go on top of the UIView backgroundPickerView. This is my code:
CGPoint center = currentButton.center;
CGPoint rootViewPoint = [currentButton.superview convertPoint:center toView:self.view];
NSIndexPath *indexPath = [measurementTableView indexPathForRowAtPoint:rootViewPoint];
CGRect cellRect = [measurementTableView rectForRowAtIndexPath:indexPath];
if (cellRect.origin.y + cellRect.size.height >= backgroundPickerView.frame.origin.y) {
[measurementTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
CGPoint offset = measurementTableView.contentOffset;
offset.y += ((cellRect.origin.y - cellRect.size.height) - backgroundPickerView.frame.origin.y);
[measurementTableView setContentOffset:offset animated:YES];
}
Does anyone see what I am doing wrong here?
UITableViewCell are reused,keeping a reference of a UITableViewCell's subView is not a good approach.
If the special UITableViewCell is not in UITableView's visibleCells ,its frame is undefined.
A solution is:
Create a custom UITableViewCell that has the same structure as you need.
Keep a reference of the indexpath for the custom UITableViewCell.
Use this indexpath to do the work .
I hope this will work:
[measurementTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
CGPoint offset = measurementTableView.contentOffset;
offset.y += backgroundPickerView.frame.height;
This code worked for me. Uses a different approach than the ones suggested here and it's good for what I need.
CGRect buttonFrame = [currentButton convertRect:currentButton.bounds toView:measurementTableView];
NSIndexPath *indexPath = [measurementTableView indexPathForRowAtPoint:buttonFrame.origin];
CGRect backPickFrame = [backgroundPickerView convertRect:backgroundPickerView.bounds toView:measurementTableView];
if (buttonFrame.origin.y + buttonFrame.size.height >= backPickFrame.origin.y) {
measurementTableView.contentInset = UIEdgeInsetsMake(0.0, 0.0, backgroundPickerView.frame.size.height, 0.0);
[measurementTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
} else {
[measurementTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
First problem is that UITableView is partially hidden under a keyboard. So when you trying scroll to bottom rows table will bounce back and required content is not visible.
To solve this problem when keyboard appears/hides you have two choices.
update value of self.tableView.contentInstet.bottom to take into account keyboard size
update frame of table, if you are using auto-layout then best approach will be update constant part of bottom constraint (IMO this is better approach).
After you did that you can do this:
CGRect rectToBeVisible = [currentButton convertRect: currentButton.bounds
toView: self.tableView];
[self.tableView scrollRectToVisible: rectToBeVisible animated: YES];
I could messed up view to which convertion should be performed, so experiment a bit, but general concept should be clear.

uitableview doesn't scroll to bottom

I have a UITableView where I add rows dynamically. Basically a chat app.
I need to scroll the UITableView to bottom after reloadData
My code is:
It scrolls to here:
https://dl-web.dropbox.com/get/Screen%20Shot%202014-12-05%20at%2013.04.23.png?_subject_uid=44249794&w=AADgJkJJOGK_ANH_cXWnxeXmhFmF5KHjZllg-kP66HARdw
When manually scrolling, I can scroll even further to here: https://dl-web.dropbox.com/get/Screen%20Shot%202014-12-05%20at%2013.05.19.png?_subject_uid=44249794&w=AADtQEfMHMy0Ounri5W3gBTLNgR4uckT_gBdYQel9vD1qQ
My code:
[_chatTable reloadData];
NSIndexPath* indexPath = [NSIndexPath indexPathForRow: [[AppData getChatLog]count]-1 inSection: 0];
[_chatTable scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
I need the UITableView to scroll all the way to the bottom.
Sorry,I couldn't open up the given links.Try this
UITableView *yourTableView = yourTableViewToBeSetHere;
CGRect lastCellRect = CGRectMake(0, CGFLOAT_MAX, 50, 50);
// Scroll to the particular rect
[yourTableView scrollRectToVisible:lastCellRect
animated:YES];
Good luck!

How to implement scrollViewDidScroll: method?

I'm building an article reading app.List of articles is in UITableViewController,I'm facing an issue when i use scrollViewDidScroll: method first cell of table is display under the UINavigationBar.But when commented this code it displays fine means first cell exactly after the UINavigationBar.
here is my code:
- (void)scrollViewDidScroll: (UIScrollView*)scroll {
// UITableView only moves in one direction, y axis
CGFloat currentOffset = scroll.contentOffset.y;
CGFloat maximumOffset = scroll.contentSize.height - scroll.frame.size.height;
// Change 10.0 to adjust the distance from bottom
if (maximumOffset - currentOffset <= -60.0) {
x++;
[self LoadMore];
[self.tableView addInfiniteScrollingWithActionHandler:^{
}];
[self.tableView reloadData];
}
}
This answer may not be the solution to your problem. This is to point out a major flow in your code that could be the cause of your problem.
You should not reload data [self LoadMore];[self.tableView reloadData]; directly inside scrollViewDidScroll: method. This will cause the method to be called multiple times as you scroll.
And I think you have implemented infinite loading incorrectly.
This code should be placed inside some initializer method (e.g., viewDidLoad)
[tableView addInfiniteScrollingWithActionHandler:^{
[self LoadMore];
[self.tableView reloadData];
// call [tableView.infiniteScrollingView stopAnimating] when done
}];
If you are planing to load more items as you scroll, I don't think you need to use scrollViewDidScroll: at all. Simply put the above code inside viewDidLoad: and everything should work. You will have to keep track of the number of items loaded separately. Hope this will help. :)

UITableView inserting section at top while scrolling

I am inserting new section (section contains 3 cells) top of UITableView while SCROLLING TOP.
[_mainTable beginUpdates];
[_mainTable insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
[_mainTable endUpdates];
Section gets inserting properly. But it takes me top of Table i.e. cell 0 or row 0. I want this transaction to be smooth. I can insert
[_mainTable scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:1] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
after endUpdates but it shows quick jerk because it takes you top of Table then suddenly scroll it to your last position.
How can i make it smooth.
Thanks
I haven't done exhaustive testing on this, but this seems promising:
Identify NSIndexPath of one of the visible cells.
Get its rectForRowAtIndexPath.
Get the current contentOffset of the table, itself.
Add the section, but call reloadData instead of insertSections (which prevents jarring scrolling).
Get the updated rectForRowAtIndexPath that you got in step 2.
Update contentOffset by the difference of the result from step 5 and that of step 2.
Thus:
[self.sections insertObject:newSection atIndex:0]; // this is my model backing my table
NSIndexPath *oldIndexPath = self.tableView.indexPathsForVisibleRows[0]; // 1
CGRect before = [self.tableView rectForRowAtIndexPath:oldIndexPath]; // 2
CGPoint contentOffset = [self.tableView contentOffset]; // 3
[self.tableView reloadData]; // 4
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:oldIndexPath.row inSection:oldIndexPath.section + 1];
CGRect after = [self.tableView rectForRowAtIndexPath:newIndexPath]; // 5
contentOffset.y += (after.origin.y - before.origin.y);
self.tableView.contentOffset = contentOffset; // 6

Changing a specific uitableviewcell row height while scrolling a uitableview

I have a UITableview with 2 sections, 1 row in the 1st section, and a variable amount of rows for the second section. When the user scrolls the table up (finger moving upwards), then the tableview does it's default thing, but when the user is at the top of the uitableview and scrolls down (finger moving downwards) then it should look like the first cell in the first section height increases as much as the user scrolls down (and releasing the touch will change the height of the row back to it's original height of 100). I tried
-(void)scrollViewDidScroll:(UIScrollView*)scrollView{
if(scrollView.contentOffset.y < 0){
[mainTable reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection: 0]] withRowAnimation:UITableViewRowAnimationNone];
}
}
-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{
if(indexPath.section == 0 && tableView.contentOffset.y < 0){
return -tableView.contentOffset.y+100;//Default height is 100
}
}
but the reloadRows method resets the contentOffset to 0 so the tableview just stutters when i pull down. It seems like if this doesn't work, then i'll have to write everything on a UIScrollView and it seems like a huge pain without recyclable cells.
Does anybody have any suggestions?
No need to reload the row, i just changed the frame directly. Make sure you set the cell.layer.masksToBounds = YES and make the subViews in the cell to be larger than the original cell height.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
if (mainTable.contentOffset.y < 0) {
UITableViewCell *cell = [mainTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
float rawr = mainTable.contentOffset.y;
cell.frame = CGRectMake(cell.frame.origin.x, rawr, cell.frame.size.width, 100-rawr);
}
}

Resources