UITableView contentOffSet is not working properly

孤人 提交于 2019-11-28 19:23:02

This worked for me:

// contentOffset will not change before the main runloop ends without queueing it, for iPad that is
dispatch_async(dispatch_get_main_queue(), ^{
    // The search bar is hidden when the view becomes visible the first time
    self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(self.searchBar.bounds));
});

Put it in your -viewDidLoad or -viewWillAppear

In earlier versions of the iOS SDK, methods such as viewWillAppear ran on the main thread, they now run on a background thread which is why the issue now occurs.

Most callbacks tend to fire on a background thread so always check for thread safety when doing UI calls.

Dispatch the change to the content offset on the main thread:

Objective C

dispatch_async(dispatch_get_main_queue(), ^{
    CGPoint offset = CGPointMake(0, self.searchBar.bounds.height)
    [self.tableView setContentOffset:offset animated:NO];
});

Swift 3

DispatchQueue.main.async {
            let offset = CGPoint.init(x: 0, y: self.searchBar.bounds.height)
            self.tableView.setContentOffset(offset, animated: false)
        }

Not sure what the reason is (don't have time to research it right now), but I solved this issue by using performSelector after a delay of 0. Example:

- (void)viewWillAppear:(BOOL)animated {
    ...
    [self performSelector:@selector(hideSearchBar) withObject:nil afterDelay:0.0f];
}

- (void)hideSearchBar {
    self.tableView.contentOffset = CGPointMake(0, 44);
}
Kishor

This worked for me.

self.tableView.beginUpdates()
self.tableView.setContentOffset( CGPoint(x: 0.0, y: 0.0), animated: false)
self.tableView.endUpdates()

Objective-C :

[_tableView beginUpdates];
[_tableView setContentOffset:CGPointMake(0, 0)];
[_tableView endUpdates];
techniao

It may be because of the "Adjust Scroll View Insets" attribute on the View Controller. See this: https://stackoverflow.com/a/22022366

EDIT: Be sure to check the value of 'contentInset' to see what's happening, since this also has an effect on the scroll view. This value is changed after viewWillAppear: when "Adjust Scroll View Insets" is set, which seems to be what others are trying to avoid by using dispatch queues and the like.

After one hour of tests the only way that works 100% is this one:

-(void)hideSearchBar
{
    if([self.tableSearchBar.text length]<=0 && !self.tableSearchBar.isFirstResponder)
    {
        self.tableView.contentOffset = CGPointMake(0, self.tableSearchBar.bounds.size.height);
        self.edgesForExtendedLayout = UIRectEdgeBottom;
    }
}

-(void)viewDidLayoutSubviews
{
    [self hideSearchBar];
}

with this approach you can always hide the search bar if is empty

In my case the problem was that I called

 [_myGreatTableView reloadData];

before getting the _tableView.contentOffset.y. This always returned '0'.

So I switched the order of these methods and now it works.

This is quite a strange behavior in my opinion, because offset returned 0 but the UI still kept the scroll position of the table.

I fixed it with layoutIfNeeded()

    self.articlesCollectionView.reloadData()
    self.articlesCollectionView.layoutIfNeeded()
    self.articlesCollectionView.setContentOffset(CGPoint(x: 0, y: 40), animated: false)
Dhara

The problem is auto masking. Select your table and make sure you have selected all the lines, as in the image below.

The line of code is working as it should.

Explaination of contentOffset of a UITableView:

For example, if you have a table view of height 100. Its content may be more than it's view, say 150. contentOffset will tell the table from where in the content to start from. Say contentOffset = (0, 40), the content will be shown after 40 of it's height.

Note: Once the content is scrolled, there is no affect of the previously set contentOffset.

parilogic

You need to hide the search bar by yourself when you scroll the table. So don't put it as a UITableView header. You could hide it by setting its height to zero. That way if your table view is set to auto resize, it will expand.

uranpro

The problem may be with the search bar size. Try the following line of code.

[searchBar sizeToFit];
drdrdrdr

If your table will always have at least one row, just scroll to the first row of the table and the search bar will be hidden automatically.

let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)

self.tableView.selectRowAtIndexPath(firstIndexPath, animated: false, scrollPosition: .Top)

If you put the above code on viewDidLoad, it will throw an error because the tableView hasn't loaded yet, so you have to put it in viewDidAppear because by this point the tableView has already loaded.

If you put it on viewDidAppear, everytime you open the tableView it will scroll to the top.

Maybe you don't want this behaviour if the tableView remains open, like when it is a UITabBar View Controller or when you do a segue and then come back. If you just want it to scroll to the top on the initial load, you can create a variable to check if it is an initial load so that it scrolls to the top just once.

First define a variable called isInitialLoad in the view controller class and set it to "true":

var isInitialLoad = true

And then check if isInitialLoad is true on viewDidAppear and if it is true, scroll to the top and set the isInitialLoad variable to false:

if isInitialLoad {
    let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)
    self.tableView.selectRowAtIndexPath(firstIndexPath, animated: false, scrollPosition: .Top)
    isInitialLoad = false
}

In iOS 7/8/9 simple self.automaticallyAdjustsScrollViewInsets = NO; solved the problem in my case

Angelote
self.tableView.contentInset = UIEdgeInsetsMake(self.navigationController.navigationBar.frame.size.height -80, 0, 0, 0);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!