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. :)
Related
I have a UITableView that is populated with cells of variable height. I would like the table to scroll to the bottom when the view is pushed into view.
I currently have the following function:
[self.table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
I'm using autolayout, dynamic table cells and UITableViewAutomaticDimension as row height. I set estimatedRowHeight = 100
The above code works fine in viewDidLoad however this has the unfortunate side effect of displaying the top of the table when the view first appears and then jumping to the bottom. I would prefer it if the table view could be scrolled to the bottom before it appears.
Please note: I'm loading data from core data.
Any guidance would be much appreciated, even if it's just a case of telling me what I have is all that is possible.
Theoretically, the order of the calls is correct: viewDidLoad should be called before the view is rendered, so the only thing that comes to my mind is that probably scrollToRowAtIndexPath:atScrollPosition:animated: is asynchronous. Maybe there's something you can do with UIScrollViewDelegate (remember, UITableView inherits from UIScrollView) - https://developer.apple.com/documentation/uikit/uiscrollviewdelegate?language=objc
Maybe you can do something like hiding the view on onLoad and showing it on scrollViewDidScroll:. I don't have time to test and paste a snippet but... maybe it helps :) Good luck!
This seems pretty reliable...
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 100;
[self.tableView performBatchUpdates:nil completion:^(BOOL b) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:numRows - 1 inSection:numSections - 1];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}];
}
Replace numRows and numSections with your data count(s).
No matter what I do, I cannot get my tableview to scroll to the very bottom when a user gets to my viewcontroller. I'm currently using the following code to try and accomplish this:
ViewController.m
-(void)viewDidAppear {
if (self.tableView.contentSize.height > self.tableView.frame.size.height)
{
CGPoint offset = CGPointMake(0, self.tableView.contentSize.height - self.tableView.frame.size.height);
[self.tableView setContentOffset:offset animated:YES];
}
}
I've also tried pasting this in viewDidLoad, as well as viewWillAppear, and no dice whatsoever. And yes, I am using autolayout. Any ideas?
I have a custom cell which should be spaced from the edges of the display. For that I use this:
- (void)setFrame:(CGRect)frame {
frame.origin.x += kCellSidesInset;
frame.size.width -= 2 * kCellSidesInset;
[super setFrame:frame];
}
I do have a button that hides/shows the bottom view of a stacked view inside the cell. For which I use this code:
- (IBAction)showCardDetails:(id)sender {
UITableView *cellTableView = (UITableView*)[[[[sender superview] superview] superview] superview ];
[cellTableView beginUpdates];
self.details.hidden = !self.details.hidden;
[cellTableView endUpdates];
// [cellTableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationBottom];
// [cellTableView reloadData];
}
However when the table is updated to reflect the change the right padding becomes allot bigger. Then when I scroll a bit it gets fixed.
As much as I could visually judge it is like 3 times. Maybe it adds two more kCellSidesInset on the right but I doubt it.
Why is this happening and how can it be fixed? Maybe it can be avoid by instead of giving inset to the cell giving it to the UITableView (I have some trouble figuring how to do this).
PS. All the code is inside the CustomCell.m. I am open for a suggestion to a better way of getting the UITableView inside the action. Should I use selector in the CustomTableViewController.m to implement the action there when the cell is added?
EDIT: From what I can see the re rendering of the cells goes trough three phases.
Phase one, a couple of these:
Phase two, it updates the view cells:
And here everything looks good for now. The view that I want to hide/show is hidden/shown and all is good but then some sort of cleanup breaks the layout:
I solved the problem by refactoring the setFrame method to use the superview's frame of the cell as a reference point for the cell frame
- (void)setFrame:(CGRect)frame {
frame.origin.x = self.superview.frame.origin.x + kCellSidesInset;
frame.size.width = self.superview.frame.size.width - 2 * kCellSidesInset;
[super setFrame:frame];
}
I saw many answers in SO which describes how can I scroll UITableView to the specific position.
I use setContentOffset for scrolling to particular position.
I meet a weird issue. If my tableView is half scrolled then setContentOffset is working properly. But when I scroll to end of the tableView and then use setContentOffset, table view scrolls a little bit more.
My setContentOffset value is CGPoint(0,199).
[self.tableView setContentOffset:CGPointMake(0,199) animated:NO];
After reaching a bottom I use setContentOffset. Then I check the contentOffset of UITableView. and it is 169.
I am not able to figure it out what exactly the issue is.
Edit::
I am using the following code. When a button in the last cell is pressed:
- (void)userPressedSubmitButtonOnLastCell
{
[self updateData];
[self.tableView reloadData];
[self performSelector:#selector(scrollTableView) withObject:nil afterDelay:0.5];
}
- (void)scrollTableView
{
[self.tableView setContentOffset:CGPointMake(0,199) animated:NO];
}
Why don't you use tableView scrollToRowAtIndexPath: or tableView scrollRectToVisible:(CGRect)? This will allow you to scroll to either specific row or rectangle. ContentOffset is more suitable for UIScrollView.
When my View (containing a Table View) loads, I want it to scroll to the bottom of the table view. This works great. However, when one of my buttons (sendReply) is tapped, I also want the tableView to scroll to the bottom. For some reason, scrolling to the bottom of the tableView works when the View is initially loaded, however [self bottomScroll:self] doesn't seem to fire when I place it inside of my sendReply action?
.m
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self bottomScroll:self];
}
- (void)bottomScroll:(id)sender {
if (self.messages.count > 0)
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.messages.count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
- (IBAction)sendReply:(id)sender {
[self bottomScroll:self];
}
This should work. Are you sure messages.count is greater than 0 when you tap the button? You can set a breakpoint at that line and see if this code is executed.
Also you can try -scrollRectToVisible as an alternative.
as phi stated scrollRectToVisible would be the way I would go. Call your tableView's scroll view passing in the rect of your button you want to show. It's been awhile since I've used obj-c but:
-(IBAction)sendReply: (id)sender {
[scrollView scrollRectToVisible: sendReply.frame, animated: YES]
}
? The syntax may be wrong there but it should be close enough to get you where you are going.
In swift:
#IBAction func sendReply(sender: UIButton/AnyObject) -> Void {
let scrollView = tableView.scrollView
scrollView.scrollrectToVisible(_ rect: sender.frame, animated: true)
}
It seems strange based on your description. Need more code to find whats going on. What can be inferred is you want to scroll the last cell to the bottom. So make sure the contentsize of tableview is larger than its frame vertically.
Try this one
if (self.tableView.contentSize.height > self.tableView.frame.size.height){
CGPoint point = CGPointMake(0, self.tableView.contentSize.height - self.tableView.frame.size.height);
[self.tableView setContentOffset:point];
}