UITableView contentOffSet is not working properly

非 Y 不嫁゛ 提交于 2019-11-27 12:15:46

问题


In viewWillAppear, I have added UISearchBar as my headerview of UITableView. When view loads, I hides UISearchbar under UINavigationBar using contentOffSet of UITableView. When user pull down the tableview the searchbar gets displayed.

After adding headerview I hides it using below code.

self.tableView.contentOffset = CGPointMake(0, 40); //My searhbar height is 40

But at times contentOffSet is not hiding headerview. What can be the mistake.


回答1:


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




回答2:


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)
        }



回答3:


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);
}



回答4:


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];



回答5:


I fixed it with layoutIfNeeded()

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



回答6:


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.




回答7:


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




回答8:


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.




回答9:


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




回答10:


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.




回答11:


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.




回答12:


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

[searchBar sizeToFit];



回答13:


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
}



回答14:


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




回答15:


self.tableView.contentInset = UIEdgeInsetsMake(self.navigationController.navigationBar.frame.size.height -80, 0, 0, 0);


来源:https://stackoverflow.com/questions/15222186/uitableview-contentoffset-is-not-working-properly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!